RawInput.cs
author StephaneLenclud
Sun, 15 Feb 2015 12:10:40 +0100
changeset 57 878e0b271c11
parent 23 743cadfacda0
child 60 687cace560d2
permissions -rw-r--r--
Win32Hid: improved button caps structure.
sl@10
     1
using System;
sl@10
     2
using System.Runtime.InteropServices;
sl@10
     3
using System.Diagnostics;
sl@10
     4
sl@10
     5
sl@47
     6
namespace Win32.Utils
sl@10
     7
{
sl@17
     8
    /// <summary>
sl@17
     9
    /// Provide some utility functions for raw input handling.
sl@17
    10
    /// </summary>
sl@10
    11
    static class RawInput
sl@10
    12
    {
sl@10
    13
        /// <summary>
sl@10
    14
        /// 
sl@10
    15
        /// </summary>
sl@10
    16
        /// <param name="aRawInputHandle"></param>
sl@10
    17
        /// <param name="aRawInput"></param>
sl@10
    18
        /// <param name="rawInputBuffer">Caller must free up memory on the pointer using Marshal.FreeHGlobal</param>
sl@10
    19
        /// <returns></returns>
sl@10
    20
        public static bool GetRawInputData(IntPtr aRawInputHandle, ref RAWINPUT aRawInput, ref IntPtr rawInputBuffer)
sl@10
    21
        {
sl@10
    22
            bool success = true;
sl@10
    23
            rawInputBuffer = IntPtr.Zero;
sl@10
    24
sl@10
    25
            try
sl@10
    26
            {
sl@10
    27
                uint dwSize = 0;
sl@10
    28
                uint sizeOfHeader = (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
sl@10
    29
sl@10
    30
                //Get the size of our raw input data.
sl@10
    31
                Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, IntPtr.Zero, ref dwSize, sizeOfHeader);
sl@10
    32
sl@10
    33
                //Allocate a large enough buffer
sl@10
    34
                 rawInputBuffer = Marshal.AllocHGlobal((int)dwSize);
sl@10
    35
sl@10
    36
                //Now read our RAWINPUT data
sl@10
    37
                if (Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, rawInputBuffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
sl@10
    38
                {
sl@10
    39
                    return false;
sl@10
    40
                }
sl@10
    41
sl@10
    42
                //Cast our buffer
sl@10
    43
                aRawInput = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT));
sl@10
    44
            }
sl@10
    45
            catch
sl@10
    46
            {
sl@10
    47
                Debug.WriteLine("GetRawInputData failed!");
sl@10
    48
                success = false;
sl@10
    49
            }
sl@10
    50
sl@10
    51
            return success;
sl@10
    52
        }
sl@10
    53
sl@10
    54
        /// <summary>
sl@10
    55
        /// 
sl@10
    56
        /// </summary>
sl@47
    57
        /// <param name="hDevice"></param>
sl@47
    58
        /// <param name="deviceInfo"></param>
sl@10
    59
        /// <returns></returns>
sl@10
    60
        public static bool GetDeviceInfo(IntPtr hDevice, ref RID_DEVICE_INFO deviceInfo)
sl@10
    61
        {
sl@10
    62
            bool success = true;
sl@10
    63
            IntPtr deviceInfoBuffer = IntPtr.Zero;
sl@10
    64
            try
sl@10
    65
            {
sl@10
    66
                //Get Device Info
sl@10
    67
                uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
sl@10
    68
                deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize);
sl@10
    69
sl@23
    70
                int res = Win32.Function.GetRawInputDeviceInfo(hDevice, Const.RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize);
sl@10
    71
                if (res <= 0)
sl@10
    72
                {
sl@10
    73
                    Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString());
sl@10
    74
                    return false;
sl@10
    75
                }
sl@10
    76
sl@10
    77
                //Cast our buffer
sl@10
    78
                deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO));
sl@10
    79
            }
sl@10
    80
            catch
sl@10
    81
            {
sl@10
    82
                Debug.WriteLine("GetRawInputData failed!");
sl@10
    83
                success = false;
sl@10
    84
            }
sl@10
    85
            finally
sl@10
    86
            {
sl@10
    87
                //Always executes, prevents memory leak
sl@10
    88
                Marshal.FreeHGlobal(deviceInfoBuffer);
sl@10
    89
            }
sl@10
    90
sl@10
    91
            
sl@10
    92
            return success;
sl@10
    93
        }
sl@10
    94
sl@17
    95
        /// <summary>
sl@19
    96
        /// Fetch pre-parsed data corresponding to HID descriptor for the given HID device.
sl@17
    97
        /// </summary>
sl@17
    98
        /// <param name="device"></param>
sl@17
    99
        /// <returns></returns>
sl@17
   100
        public static IntPtr GetPreParsedData(IntPtr hDevice)
sl@17
   101
        {
sl@17
   102
            uint ppDataSize = 256;
sl@23
   103
            int result = Win32.Function.GetRawInputDeviceInfo(hDevice, Win32.Const.RIDI_PREPARSEDDATA, IntPtr.Zero, ref ppDataSize);
sl@17
   104
            if (result != 0)
sl@17
   105
            {
sl@17
   106
                Debug.WriteLine("Failed to get raw input pre-parsed data size" + result + Marshal.GetLastWin32Error());
sl@17
   107
                return IntPtr.Zero;
sl@17
   108
            }
sl@17
   109
sl@17
   110
            IntPtr ppData = Marshal.AllocHGlobal((int)ppDataSize);
sl@23
   111
            result = Win32.Function.GetRawInputDeviceInfo(hDevice, Win32.Const.RIDI_PREPARSEDDATA, ppData, ref ppDataSize);
sl@17
   112
            if (result <= 0)
sl@17
   113
            {
sl@17
   114
                Debug.WriteLine("Failed to get raw input pre-parsed data" + result + Marshal.GetLastWin32Error());
sl@17
   115
                return IntPtr.Zero;
sl@17
   116
            }
sl@17
   117
            return ppData;
sl@17
   118
        }
sl@17
   119
sl@22
   120
        /// <summary>
sl@22
   121
        /// 
sl@22
   122
        /// </summary>
sl@22
   123
        /// <param name="device"></param>
sl@22
   124
        /// <returns></returns>
sl@22
   125
        public static string GetDeviceName(IntPtr device)
sl@22
   126
        {
sl@22
   127
            uint deviceNameSize = 256;
sl@23
   128
            int result = Win32.Function.GetRawInputDeviceInfo(device, Win32.Const.RIDI_DEVICENAME, IntPtr.Zero, ref deviceNameSize);
sl@22
   129
            if (result != 0)
sl@22
   130
            {
sl@22
   131
                return string.Empty;
sl@22
   132
            }
sl@22
   133
sl@22
   134
            IntPtr deviceName = Marshal.AllocHGlobal((int)deviceNameSize * 2);  // size is the character count not byte count
sl@22
   135
            try
sl@22
   136
            {
sl@23
   137
                result = Win32.Function.GetRawInputDeviceInfo(device, Win32.Const.RIDI_DEVICENAME, deviceName, ref deviceNameSize);
sl@22
   138
                if (result > 0)
sl@22
   139
                {
sl@23
   140
                    return Marshal.PtrToStringAnsi(deviceName, result - 1); // -1 for NULL termination
sl@22
   141
                }
sl@22
   142
sl@22
   143
                return string.Empty;
sl@22
   144
            }
sl@22
   145
            finally
sl@22
   146
            {
sl@22
   147
                Marshal.FreeHGlobal(deviceName);
sl@22
   148
            }
sl@22
   149
        }
sl@22
   150
sl@17
   151
sl@10
   152
    }
sl@10
   153
}