RawInput.cs
author StephaneLenclud
Sun, 15 Feb 2015 23:16:57 +0100
changeset 67 bda062e75e47
parent 64 8c2380995bb7
child 69 b27d6b8527e2
permissions -rw-r--r--
Adding status bar to show the device that just sent an event.
     1 using System;
     2 using System.Runtime.InteropServices;
     3 using System.Diagnostics;
     4 using System.Windows.Forms;
     5 
     6 
     7 namespace Win32
     8 {
     9     /// <summary>
    10     /// Provide some utility functions for raw input handling.
    11     /// </summary>
    12     static class RawInput
    13     {
    14         /// <summary>
    15         /// 
    16         /// </summary>
    17         /// <param name="aRawInputHandle"></param>
    18         /// <param name="aRawInput"></param>
    19         /// <param name="rawInputBuffer">Caller must free up memory on the pointer using Marshal.FreeHGlobal</param>
    20         /// <returns></returns>
    21         public static bool GetRawInputData(IntPtr aRawInputHandle, ref RAWINPUT aRawInput, ref IntPtr rawInputBuffer)
    22         {
    23             bool success = true;
    24             rawInputBuffer = IntPtr.Zero;
    25 
    26             try
    27             {
    28                 uint dwSize = 0;
    29                 uint sizeOfHeader = (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
    30 
    31                 //Get the size of our raw input data.
    32                 Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, IntPtr.Zero, ref dwSize, sizeOfHeader);
    33 
    34                 //Allocate a large enough buffer
    35                  rawInputBuffer = Marshal.AllocHGlobal((int)dwSize);
    36 
    37                 //Now read our RAWINPUT data
    38                 if (Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, rawInputBuffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
    39                 {
    40                     return false;
    41                 }
    42 
    43                 //Cast our buffer
    44                 aRawInput = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT));
    45             }
    46             catch
    47             {
    48                 Debug.WriteLine("GetRawInputData failed!");
    49                 success = false;
    50             }
    51 
    52             return success;
    53         }
    54 
    55         /// <summary>
    56         /// 
    57         /// </summary>
    58         /// <param name="hDevice"></param>
    59         /// <param name="deviceInfo"></param>
    60         /// <returns></returns>
    61         public static bool GetDeviceInfo(IntPtr hDevice, ref RID_DEVICE_INFO deviceInfo)
    62         {
    63             bool success = true;
    64             IntPtr deviceInfoBuffer = IntPtr.Zero;
    65             try
    66             {
    67                 //Get Device Info
    68                 uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
    69                 deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize);
    70 
    71                 int res = Win32.Function.GetRawInputDeviceInfo(hDevice, Win32.RawInputDeviceInfoType.RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize);
    72                 if (res <= 0)
    73                 {
    74                     Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString());
    75                     return false;
    76                 }
    77 
    78                 //Cast our buffer
    79                 deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO));
    80             }
    81             catch
    82             {
    83                 Debug.WriteLine("GetRawInputData failed!");
    84                 success = false;
    85             }
    86             finally
    87             {
    88                 //Always executes, prevents memory leak
    89                 Marshal.FreeHGlobal(deviceInfoBuffer);
    90             }
    91 
    92             
    93             return success;
    94         }
    95 
    96         /// <summary>
    97         /// Fetch pre-parsed data corresponding to HID descriptor for the given HID device.
    98         /// </summary>
    99         /// <param name="device"></param>
   100         /// <returns></returns>
   101         public static IntPtr GetPreParsedData(IntPtr hDevice)
   102         {
   103             uint ppDataSize = 0;
   104             int result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, IntPtr.Zero, ref ppDataSize);
   105             if (result != 0)
   106             {
   107                 Debug.WriteLine("Failed to get raw input pre-parsed data size" + result + Marshal.GetLastWin32Error());
   108                 return IntPtr.Zero;
   109             }
   110 
   111             IntPtr ppData = Marshal.AllocHGlobal((int)ppDataSize);
   112             result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, ppData, ref ppDataSize);
   113             if (result <= 0)
   114             {
   115                 Debug.WriteLine("Failed to get raw input pre-parsed data" + result + Marshal.GetLastWin32Error());
   116                 return IntPtr.Zero;
   117             }
   118             return ppData;
   119         }
   120 
   121         /// <summary>
   122         /// 
   123         /// </summary>
   124         /// <param name="device"></param>
   125         /// <returns></returns>
   126         public static string GetDeviceName(IntPtr device)
   127         {
   128             uint deviceNameSize = 256;
   129             int result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, IntPtr.Zero, ref deviceNameSize);
   130             if (result != 0)
   131             {
   132                 return string.Empty;
   133             }
   134 
   135             IntPtr deviceName = Marshal.AllocHGlobal((int)deviceNameSize * 2);  // size is the character count not byte count
   136             try
   137             {
   138                 result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, deviceName, ref deviceNameSize);
   139                 if (result > 0)
   140                 {
   141                     return Marshal.PtrToStringAnsi(deviceName, result - 1); // -1 for NULL termination
   142                 }
   143 
   144                 return string.Empty;
   145             }
   146             finally
   147             {
   148                 Marshal.FreeHGlobal(deviceName);
   149             }
   150         }
   151 
   152 
   153         /// <summary>
   154         /// 
   155         /// </summary>
   156         /// <param name="aTreeView"></param>
   157         public static void PopulateDeviceList(TreeView aTreeView)
   158         {
   159 
   160             //Get our list of devices
   161             RAWINPUTDEVICELIST[] ridList = null;
   162             uint deviceCount = 0;
   163             int res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount,(uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)));
   164             if (res == -1)
   165             {
   166                 //Just give up then
   167                 return;
   168             }
   169 
   170             ridList = new RAWINPUTDEVICELIST[deviceCount];
   171             res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount, (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)));
   172             if (res != deviceCount)
   173             {
   174                 //Just give up then
   175                 return;
   176             }
   177 
   178             //For each our device add a node to our treeview
   179             foreach (RAWINPUTDEVICELIST device in ridList)
   180             {
   181                 Hid.HidDevice hidDevice=new Hid.HidDevice(device.hDevice);
   182 
   183                 TreeNode node = null;
   184                 if (hidDevice.Product != null && hidDevice.Product.Length > 1)
   185                 {
   186                     //Add the devices with a proper name at the top
   187                     node = aTreeView.Nodes.Insert(0, hidDevice.Name, hidDevice.FriendlyName);
   188                 }
   189                 else
   190                 {
   191                     //Add other once at the bottom
   192                     node = aTreeView.Nodes.Add(hidDevice.Name, "0x" + hidDevice.FriendlyName);
   193                 }
   194 
   195                 node.Nodes.Add("Manufacturer: " + hidDevice.Manufacturer);
   196                 node.Nodes.Add("Product ID: 0x" + hidDevice.ProductId.ToString("X4"));
   197                 node.Nodes.Add("Vendor ID: 0x" + hidDevice.VendorId.ToString("X4"));
   198                 node.Nodes.Add("Version: " + hidDevice.Version);
   199                 node.Nodes.Add(hidDevice.Info.dwType.ToString());
   200                 if (hidDevice.Info.dwType == RawInputDeviceType.RIM_TYPEHID)
   201                 {
   202                     node.Nodes.Add("UsagePage / UsageCollection: 0x" + hidDevice.Info.hid.usUsagePage.ToString("X4") + " / 0x" + hidDevice.Info.hid.usUsage.ToString("X4"));
   203                 }
   204 
   205                 if (hidDevice.InputCapabilitiesDescription != null)
   206                 {
   207                     node.Nodes.Add(hidDevice.InputCapabilitiesDescription);
   208                 }
   209 
   210                 if (hidDevice.InputValueCapabilities != null)
   211                 {
   212                     foreach (HIDP_VALUE_CAPS caps in hidDevice.InputValueCapabilities)
   213                     {
   214                         string des = hidDevice.InputValueCapabilityDescription(caps);
   215                         if (des != null)
   216                         {
   217                             node.Nodes.Add(des);
   218                         }
   219                     }
   220 
   221                 }
   222 
   223                 node.Nodes.Add(hidDevice.Name);
   224             }
   225         }
   226 
   227     }
   228 }