HidDevice.cs
author StephaneLenclud
Sun, 15 Feb 2015 11:53:36 +0100
changeset 56 cace0afae0fa
parent 55 08c70af8af84
child 58 7ef0f9dc229c
permissions -rw-r--r--
HidDevice now supports capabilities and button capabilities.
     1 using System;
     2 using System.Windows.Forms;
     3 using System.Runtime.InteropServices;
     4 using System.Diagnostics;
     5 using System.Text;
     6 using Microsoft.Win32.SafeHandles;
     7 using Win32;
     8 
     9 namespace Hid
    10 {
    11     /// <summary>
    12     /// Represent a HID device.
    13     /// </summary>
    14     public class HidDevice: IDisposable
    15     {
    16         public string Name { get; private set; }
    17         public string Manufacturer { get; private set; }
    18         public string Product { get; private set; }
    19         public ushort VendorId { get; private set; }
    20         public ushort ProductId { get; private set; }
    21         public ushort Version { get; private set; }
    22         //Pre-parsed HID descriptor
    23         public IntPtr PreParsedData {get; private set;}
    24         //Info
    25         public RID_DEVICE_INFO Info { get {return iInfo;} }
    26         private RID_DEVICE_INFO iInfo;
    27         //Capabilities
    28         public HIDP_CAPS Capabilities { get { return iCapabilities; } }
    29         private HIDP_CAPS iCapabilities;
    30         //Input Button Capabilities
    31         public HIDP_BUTTON_CAPS[] InputButtonCapabilities { get { return iInputButtonCapabilities; } }
    32         private HIDP_BUTTON_CAPS[] iInputButtonCapabilities;
    33         
    34 
    35         /// <summary>
    36         /// Class constructor will fetch this object properties from HID sub system.
    37         /// </summary>
    38         /// <param name="hRawInputDevice">Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as rawinput.header.hDevice</param>
    39         public HidDevice(IntPtr hRawInputDevice)
    40         {
    41             //Try construct and rollback if needed
    42             try
    43             {
    44                 Construct(hRawInputDevice);
    45             }
    46             catch (System.Exception ex)
    47             {
    48                 //Just rollback and propagate
    49                 Dispose();
    50                 throw ex;
    51             }
    52         }
    53 
    54 
    55         /// <summary>
    56         /// Make sure dispose is called even if the user forgot about it.
    57         /// </summary>
    58         ~HidDevice()
    59         {
    60             Dispose();
    61         }
    62 
    63         /// <summary>
    64         /// Private constructor.
    65         /// </summary>
    66         /// <param name="hRawInputDevice"></param>
    67         private void Construct(IntPtr hRawInputDevice)
    68         {
    69             PreParsedData = IntPtr.Zero;
    70             //Fetch various information defining the given HID device
    71             Name = Win32.Utils.RawInput.GetDeviceName(hRawInputDevice);
    72 
    73             //Get our HID descriptor pre-parsed data
    74             PreParsedData = Win32.Utils.RawInput.GetPreParsedData(hRawInputDevice);
    75             if (PreParsedData == IntPtr.Zero)
    76             {
    77                 throw new Exception("HidDevice: GetPreParsedData failed: " + Marshal.GetLastWin32Error().ToString());
    78             }
    79 
    80             //Fetch device info
    81             iInfo = new RID_DEVICE_INFO();
    82             if (!Win32.Utils.RawInput.GetDeviceInfo(hRawInputDevice, ref iInfo))
    83             {
    84                 throw new Exception("HidDevice: GetDeviceInfo failed: " + Marshal.GetLastWin32Error().ToString());
    85             }
    86 
    87             //Open our device from the device name/path
    88             SafeFileHandle handle = Win32.Function.CreateFile(Name,
    89                 Win32.FileAccess.NONE,
    90                 Win32.FileShare.FILE_SHARE_READ | Win32.FileShare.FILE_SHARE_WRITE,
    91                 IntPtr.Zero,
    92                 Win32.CreationDisposition.OPEN_EXISTING,
    93                 Win32.FileFlagsAttributes.FILE_FLAG_OVERLAPPED,
    94                 IntPtr.Zero
    95                 );
    96 
    97             //Check if CreateFile worked
    98             if (handle.IsInvalid)
    99             {
   100                 throw new Exception("HidDevice: CreateFile failed: " + Marshal.GetLastWin32Error().ToString());
   101             }
   102 
   103             //Get manufacturer string
   104             StringBuilder manufacturerString = new StringBuilder(256);
   105             if (Win32.Function.HidD_GetManufacturerString(handle, manufacturerString, manufacturerString.Capacity))
   106             {
   107                 Manufacturer = manufacturerString.ToString();
   108             }
   109 
   110             //Get product string
   111             StringBuilder productString = new StringBuilder(256);
   112             if (Win32.Function.HidD_GetProductString(handle, productString, productString.Capacity))
   113             {
   114                 Product = productString.ToString();
   115             }
   116 
   117             //Get attributes
   118             Win32.HIDD_ATTRIBUTES attributes = new Win32.HIDD_ATTRIBUTES();
   119             if (Win32.Function.HidD_GetAttributes(handle, ref attributes))
   120             {
   121                 VendorId = attributes.VendorID;
   122                 ProductId = attributes.ProductID;
   123                 Version = attributes.VersionNumber;
   124             }
   125 
   126             handle.Close();
   127 
   128             //Get capabilities
   129             HidStatus status = Win32.Function.HidP_GetCaps(PreParsedData, ref iCapabilities);
   130             if (status != HidStatus.HIDP_STATUS_SUCCESS)
   131             {
   132                 throw new Exception("HidDevice: HidP_GetCaps failed: " + status.ToString());
   133             }
   134 
   135             //Get input button caps
   136             iInputButtonCapabilities = new HIDP_BUTTON_CAPS[Capabilities.NumberInputButtonCaps];
   137             ushort buttonCapabilitiesLength = Capabilities.NumberInputButtonCaps;
   138             status = Win32.Function.HidP_GetButtonCaps(HIDP_REPORT_TYPE.HidP_Input, iInputButtonCapabilities, ref buttonCapabilitiesLength, PreParsedData);
   139             if (status != HidStatus.HIDP_STATUS_SUCCESS || buttonCapabilitiesLength != Capabilities.NumberInputButtonCaps)
   140             {
   141                 throw new Exception("HidDevice: HidP_GetButtonCaps failed: " + status.ToString());
   142             }
   143             
   144 
   145         }
   146 
   147         /// <summary>
   148         /// Dispose is just for unmanaged clean-up.
   149         /// Make sure calling disposed multiple times does not crash.
   150         /// See: http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface/538238#538238
   151         /// </summary>
   152         public void Dispose()
   153         {
   154             Marshal.FreeHGlobal(PreParsedData);
   155             PreParsedData = IntPtr.Zero;
   156         }
   157 
   158         /// <summary>
   159         /// Print information about this device to our debug output.
   160         /// </summary>
   161         public void DebugWrite()
   162         {
   163             Debug.WriteLine("================ HID =========================================================================================");
   164             Debug.WriteLine("==== Name: " + Name);
   165             Debug.WriteLine("==== Manufacturer: " + Manufacturer);
   166             Debug.WriteLine("==== Product: " + Product);
   167             Debug.WriteLine("==== VendorID: 0x" + VendorId.ToString("X4"));
   168             Debug.WriteLine("==== ProductID: 0x" + ProductId.ToString("X4"));
   169             Debug.WriteLine("==== Version: " + Version.ToString());
   170             Debug.WriteLine("==============================================================================================================");
   171         }
   172 
   173     }
   174 
   175 }