1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/AssemblyInfo.cs Wed May 14 07:52:21 2014 +0200
1.3 @@ -0,0 +1,28 @@
1.4 +using System.Reflection;
1.5 +// General Information about an assembly is controlled through the following
1.6 +// set of attributes. Change these attribute values to modify the information
1.7 +// associated with an assembly
1.8 +
1.9 +[ assembly: AssemblyTitle( "USB test application for HIDs" ) ]
1.10 +[ assembly: AssemblyDescription( "www.Lvr.com" ) ]
1.11 +[ assembly: AssemblyCompany( "Lakeview Research" ) ]
1.12 +[ assembly: AssemblyProduct( "usbhidio" ) ]
1.13 +[ assembly: AssemblyCopyright( "c. 1999-2005 by Jan Axelson" ) ]
1.14 +[ assembly: AssemblyTrademark( "" ) ]
1.15 +[ assembly: AssemblyCulture( "" ) ]
1.16 +
1.17 +// Version information for an assembly consists of the following four values:
1.18 +
1.19 +// Major version
1.20 +// Minor Version
1.21 +// Revision
1.22 +// Build Number
1.23 +
1.24 +// You can specify all the values or you can default the Revision and Build Numbers
1.25 +// by using the '*' as shown below
1.26 +
1.27 +
1.28 +[ assembly: AssemblyVersion( "2.2.*" ) ]
1.29 +
1.30 +
1.31 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/ClassDiagram1.cd Wed May 14 07:52:21 2014 +0200
2.3 @@ -0,0 +1,65 @@
2.4 +<?xml version="1.0" encoding="utf-8"?>
2.5 +<ClassDiagram MajorVersion="1" MinorVersion="1">
2.6 + <Class Name="GenericHid.Debugging" Collapsed="true">
2.7 + <Position X="0.5" Y="0.5" Width="1.5" />
2.8 + <TypeIdentifier>
2.9 + <HashCode>AQAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI=</HashCode>
2.10 + <FileName>Debugging.cs</FileName>
2.11 + </TypeIdentifier>
2.12 + </Class>
2.13 + <Class Name="GenericHid.DeviceManagement" Collapsed="true">
2.14 + <Position X="2.25" Y="0.5" Width="1.5" />
2.15 + <TypeIdentifier>
2.16 + <HashCode>AAAAIQAAAAACEAABAAEAAEAgBDAgAIAQCEIAgBkAAAA=</HashCode>
2.17 + <FileName>DeviceManagement.cs</FileName>
2.18 + </TypeIdentifier>
2.19 + </Class>
2.20 + <Class Name="GenericHid.FileIO" Collapsed="true">
2.21 + <Position X="4" Y="0.5" Width="1.5" />
2.22 + <TypeIdentifier>
2.23 + <HashCode>AAQAAAAAAAAAAAAAgAQAgAgAAAAAAAAAAAABAAAAAAQ=</HashCode>
2.24 + <FileName>FileIODeclarations.cs</FileName>
2.25 + </TypeIdentifier>
2.26 + </Class>
2.27 + <Class Name="GenericHid.FrmMain">
2.28 + <Position X="0.5" Y="1.5" Width="1.5" />
2.29 + <NestedTypes>
2.30 + <Delegate Name="GenericHid.FrmMain.MarshalToForm" Collapsed="true">
2.31 + <TypeIdentifier>
2.32 + <NewMemberFileName>FrmMain.cs</NewMemberFileName>
2.33 + </TypeIdentifier>
2.34 + </Delegate>
2.35 + </NestedTypes>
2.36 + <TypeIdentifier>
2.37 + <HashCode>ICUA1BAQNaMYBREAgFCQgUIDUERCJwAKCDHCxEEQUEA=</HashCode>
2.38 + <FileName>FrmMain.cs</FileName>
2.39 + </TypeIdentifier>
2.40 + </Class>
2.41 + <Class Name="GenericHid.GenericHid" Collapsed="true">
2.42 + <Position X="2.25" Y="1.5" Width="1.5" />
2.43 + <TypeIdentifier>
2.44 + <HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAABAAAAAA=</HashCode>
2.45 + <FileName>GenericHid.cs</FileName>
2.46 + </TypeIdentifier>
2.47 + </Class>
2.48 + <Class Name="GenericHid.Hid" Collapsed="true">
2.49 + <Position X="4" Y="1.5" Width="1.5" />
2.50 + <TypeIdentifier>
2.51 + <HashCode>ADSAUARIUAAAgAQAAAAJAFEAAEgAAAAAACgVABgAACE=</HashCode>
2.52 + <FileName>Hid.cs</FileName>
2.53 + </TypeIdentifier>
2.54 + </Class>
2.55 + <Class Name="GenericHid.Properties.Resources" Collapsed="true">
2.56 + <Position X="0.5" Y="2.5" Width="1.5" />
2.57 + <TypeIdentifier>
2.58 + <HashCode>AAAAAAAAAAAAAAAAAAABEAAAAQAAAAAAAAAAAAAAAIA=</HashCode>
2.59 + </TypeIdentifier>
2.60 + </Class>
2.61 + <Class Name="GenericHid.Properties.Settings" Collapsed="true">
2.62 + <Position X="2.25" Y="2.5" Width="1.5" />
2.63 + <TypeIdentifier>
2.64 + <HashCode>AAAAAAAAAAAAAAAAAAAAIAAAAAABAAAAAAAAAAAAAAA=</HashCode>
2.65 + </TypeIdentifier>
2.66 + </Class>
2.67 + <Font Name="Tahoma" Size="10" />
2.68 +</ClassDiagram>
2.69 \ No newline at end of file
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/Debugging.cs Wed May 14 07:52:21 2014 +0200
3.3 @@ -0,0 +1,47 @@
3.4 +using System;
3.5 +
3.6 +namespace GenericHid
3.7 +{
3.8 + /// <summary>
3.9 + /// Used only in Debug.Write statements.
3.10 + /// </summary>
3.11 + ///
3.12 + internal sealed partial class Debugging
3.13 + {
3.14 + /// <summary>
3.15 + /// Get text that describes the result of an API call.
3.16 + /// </summary>
3.17 + ///
3.18 + /// <param name="functionName"> the name of the API function. </param>
3.19 + ///
3.20 + /// <returns>
3.21 + /// The text.
3.22 + /// </returns>
3.23 +
3.24 + internal String ResultOfApiCall( String functionName )
3.25 + {
3.26 + var resultString = new String(Convert.ToChar( 0 ), 129 );
3.27 +
3.28 + // Returns the result code for the last API call.
3.29 +
3.30 + Int32 resultCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
3.31 +
3.32 + // Get the result message that corresponds to the code.
3.33 +
3.34 + Int64 temp = 0;
3.35 + Int32 bytes = NativeMethods.FormatMessage(NativeMethods.FormatMessageFromSystem, ref temp, resultCode, 0, resultString, 128, 0);
3.36 +
3.37 + // Subtract two characters from the message to strip the CR and LF.
3.38 +
3.39 + if ( bytes > 2 )
3.40 + {
3.41 + resultString = resultString.Remove( bytes - 2, 2 );
3.42 + }
3.43 + // Create the String to return.
3.44 +
3.45 + resultString = Environment.NewLine + functionName + Environment.NewLine + "Result = " + resultString + Environment.NewLine;
3.46 +
3.47 + return resultString;
3.48 + }
3.49 + }
3.50 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/DebuggingDeclarations.cs Wed May 14 07:52:21 2014 +0200
4.3 @@ -0,0 +1,21 @@
4.4 +using System;
4.5 +using System.Runtime.InteropServices;
4.6 +
4.7 +namespace GenericHid
4.8 +{
4.9 + /// <summary>
4.10 + /// Win32 API declarations for Debug.Write statements.
4.11 + /// </summary>
4.12 + ///
4.13 + internal sealed partial class Debugging
4.14 + {
4.15 + internal static class NativeMethods
4.16 + {
4.17 + internal const Int16 FormatMessageFromSystem = 0X1000;
4.18 +
4.19 + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
4.20 + internal static extern Int32 FormatMessage(Int32 dwFlags, ref Int64 lpSource, Int32 dwMessageId, Int32 dwLanguageZId,
4.21 + String lpBuffer, Int32 nSize, Int32 arguments);
4.22 + }
4.23 + }
4.24 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/DeviceManagement.cs Wed May 14 07:52:21 2014 +0200
5.3 @@ -0,0 +1,252 @@
5.4 +using System;
5.5 +using System.Diagnostics;
5.6 +using System.Runtime.InteropServices;
5.7 +using System.Windows.Forms;
5.8 +
5.9 +namespace GenericHid
5.10 +{
5.11 + /// <summary>
5.12 + /// Routine for detecting devices using Win32 SetupDi functions.
5.13 + /// </summary>
5.14 + ///
5.15 + sealed internal partial class DeviceManagement
5.16 + {
5.17 + private const String ModuleName = "Device Management";
5.18 +
5.19 + /// <summary>
5.20 + /// Provides a central mechanism for exception handling.
5.21 + /// Displays a message box that describes the exception.
5.22 + /// </summary>
5.23 + ///
5.24 + /// <param name="name"> the module where the exception occurred. </param>
5.25 + /// <param name="e"> the exception </param>
5.26 +
5.27 + internal static void DisplayException(String name, Exception e)
5.28 + {
5.29 + try
5.30 + {
5.31 + // Create an error message.
5.32 +
5.33 + String message = "Exception: " + e.Message + Environment.NewLine + "Module: " + name + Environment.NewLine + "Method: " +
5.34 + e.TargetSite.Name;
5.35 +
5.36 + const String caption = "Unexpected Exception";
5.37 +
5.38 + MessageBox.Show(message, caption, MessageBoxButtons.OK);
5.39 + Debug.Write(message);
5.40 + }
5.41 + catch (Exception ex)
5.42 + {
5.43 + DisplayException(ModuleName, ex);
5.44 + throw;
5.45 + }
5.46 + }
5.47 +
5.48 + /// <summary>
5.49 + /// Use SetupDi API functions to retrieve the device path name of an
5.50 + /// attached device that belongs to a device interface class.
5.51 + /// </summary>
5.52 + ///
5.53 + /// <param name="myGuid"> an interface class GUID. </param>
5.54 + /// <param name="devicePathName"> a pointer to the device path name
5.55 + /// of an attached device. </param>
5.56 + ///
5.57 + /// <returns>
5.58 + /// True if a device is found, False if not.
5.59 + /// </returns>
5.60 +
5.61 + internal Boolean FindDeviceFromGuid(Guid myGuid, ref String[] devicePathName)
5.62 + {
5.63 + Int32 bufferSize = 0;
5.64 + var deviceInfoSet = new IntPtr();
5.65 + Boolean lastDevice = false;
5.66 + var myDeviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
5.67 +
5.68 + try
5.69 + {
5.70 + Int32 memberIndex;
5.71 +
5.72 + // ***
5.73 + // API function
5.74 +
5.75 + // summary
5.76 + // Retrieves a device information set for a specified group of devices.
5.77 + // SetupDiEnumDeviceInterfaces uses the device information set.
5.78 +
5.79 + // parameters
5.80 + // Interface class GUID.
5.81 + // Null to retrieve information for all device instances.
5.82 + // Optional handle to a top-level window (unused here).
5.83 + // Flags to limit the returned information to currently present devices
5.84 + // and devices that expose interfaces in the class specified by the GUID.
5.85 +
5.86 + // Returns
5.87 + // Handle to a device information set for the devices.
5.88 + // ***
5.89 +
5.90 + deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);
5.91 +
5.92 + bool deviceFound = false;
5.93 + memberIndex = 0;
5.94 +
5.95 + // The cbSize element of the MyDeviceInterfaceData structure must be set to
5.96 + // the structure's size in bytes.
5.97 + // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
5.98 +
5.99 + myDeviceInterfaceData.cbSize = Marshal.SizeOf(myDeviceInterfaceData);
5.100 +
5.101 + do
5.102 + {
5.103 + // Begin with 0 and increment through the device information set until
5.104 + // no more devices are available.
5.105 +
5.106 + // ***
5.107 + // API function
5.108 +
5.109 + // summary
5.110 + // Retrieves a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
5.111 + // On return, MyDeviceInterfaceData contains the handle to a
5.112 + // SP_DEVICE_INTERFACE_DATA structure for a detected device.
5.113 +
5.114 + // parameters
5.115 + // DeviceInfoSet returned by SetupDiGetClassDevs.
5.116 + // Optional SP_DEVINFO_DATA structure that defines a device instance
5.117 + // that is a member of a device information set.
5.118 + // Device interface GUID.
5.119 + // Index to specify a device in a device information set.
5.120 + // Pointer to a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
5.121 +
5.122 + // Returns
5.123 + // True on success.
5.124 + // ***
5.125 +
5.126 + Boolean success = NativeMethods.SetupDiEnumDeviceInterfaces
5.127 + (deviceInfoSet,
5.128 + IntPtr.Zero,
5.129 + ref myGuid,
5.130 + memberIndex,
5.131 + ref myDeviceInterfaceData);
5.132 +
5.133 + // Find out if a device information set was retrieved.
5.134 +
5.135 + if (!success)
5.136 + {
5.137 + lastDevice = true;
5.138 + }
5.139 + else
5.140 + {
5.141 + // A device is present.
5.142 +
5.143 + // ***
5.144 + // API function:
5.145 +
5.146 + // summary:
5.147 + // Retrieves an SP_DEVICE_INTERFACE_DETAIL_DATA structure
5.148 + // containing information about a device.
5.149 + // To retrieve the information, call this function twice.
5.150 + // The first time returns the size of the structure.
5.151 + // The second time returns a pointer to the data.
5.152 +
5.153 + // parameters
5.154 + // DeviceInfoSet returned by SetupDiGetClassDevs
5.155 + // SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces
5.156 + // A returned pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA
5.157 + // Structure to receive information about the specified interface.
5.158 + // The size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
5.159 + // Pointer to a variable that will receive the returned required size of the
5.160 + // SP_DEVICE_INTERFACE_DETAIL_DATA structure.
5.161 + // Returned pointer to an SP_DEVINFO_DATA structure to receive information about the device.
5.162 +
5.163 + // Returns
5.164 + // True on success.
5.165 + // ***
5.166 +
5.167 + NativeMethods.SetupDiGetDeviceInterfaceDetail
5.168 + (deviceInfoSet,
5.169 + ref myDeviceInterfaceData,
5.170 + IntPtr.Zero,
5.171 + 0,
5.172 + ref bufferSize,
5.173 + IntPtr.Zero);
5.174 +
5.175 + // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
5.176 +
5.177 + IntPtr detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
5.178 +
5.179 + // Store cbSize in the first bytes of the array. Adjust for 32- and 64-bit systems.
5.180 +
5.181 + Int32 cbsize;
5.182 +
5.183 + if (IntPtr.Size == 4)
5.184 + {
5.185 + cbsize = 4 + Marshal.SystemDefaultCharSize;
5.186 + }
5.187 + else
5.188 + {
5.189 + cbsize = 8;
5.190 + }
5.191 +
5.192 + Marshal.WriteInt32(detailDataBuffer, cbsize);
5.193 +
5.194 + // Call SetupDiGetDeviceInterfaceDetail again.
5.195 + // This time, pass a pointer to DetailDataBuffer
5.196 + // and the returned required buffer size.
5.197 +
5.198 + NativeMethods.SetupDiGetDeviceInterfaceDetail
5.199 + (deviceInfoSet,
5.200 + ref myDeviceInterfaceData,
5.201 + detailDataBuffer,
5.202 + bufferSize,
5.203 + ref bufferSize,
5.204 + IntPtr.Zero);
5.205 +
5.206 + // Get the address of the devicePathName.
5.207 +
5.208 + var pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
5.209 +
5.210 + // Get the String containing the devicePathName.
5.211 +
5.212 + devicePathName[memberIndex] = Marshal.PtrToStringAuto(pDevicePathName);
5.213 +
5.214 + if (detailDataBuffer != IntPtr.Zero)
5.215 + {
5.216 + // Free the memory allocated previously by AllocHGlobal.
5.217 +
5.218 + Marshal.FreeHGlobal(detailDataBuffer);
5.219 + }
5.220 + deviceFound = true;
5.221 + }
5.222 + memberIndex = memberIndex + 1;
5.223 + }
5.224 + while (!lastDevice);
5.225 +
5.226 + return deviceFound;
5.227 + }
5.228 + finally
5.229 + {
5.230 + // ***
5.231 + // API function
5.232 +
5.233 + // summary
5.234 + // Frees the memory reserved for the DeviceInfoSet returned by SetupDiGetClassDevs.
5.235 +
5.236 + // parameters
5.237 + // DeviceInfoSet returned by SetupDiGetClassDevs.
5.238 +
5.239 + // returns
5.240 + // True on success.
5.241 + // ***
5.242 +
5.243 + if (deviceInfoSet != IntPtr.Zero)
5.244 + {
5.245 + NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
5.246 + }
5.247 + }
5.248 + }
5.249 + }
5.250 +}
5.251 +
5.252 +
5.253 +
5.254 +
5.255 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/DeviceManagementDeclarations.cs Wed May 14 07:52:21 2014 +0200
6.3 @@ -0,0 +1,58 @@
6.4 +using System;
6.5 +using System.Runtime.InteropServices;
6.6 +
6.7 +namespace GenericHid
6.8 +{
6.9 + internal sealed partial class DeviceManagement
6.10 + {
6.11 + internal static class NativeMethods
6.12 + {
6.13 + ///<summary >
6.14 + // API declarations relating to device management (SetupDixxx and
6.15 + // RegisterDeviceNotification functions).
6.16 + /// </summary>
6.17 +
6.18 + // from setupapi.h
6.19 +
6.20 + internal const Int32 DIGCF_PRESENT = 2;
6.21 + internal const Int32 DIGCF_DEVICEINTERFACE = 0X10;
6.22 +
6.23 + internal struct SP_DEVICE_INTERFACE_DATA
6.24 + {
6.25 + internal Int32 cbSize;
6.26 + internal Guid InterfaceClassGuid;
6.27 + internal Int32 Flags;
6.28 + internal IntPtr Reserved;
6.29 + }
6.30 +
6.31 + internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
6.32 + {
6.33 + internal Int32 cbSize;
6.34 + internal String DevicePath;
6.35 + }
6.36 +
6.37 + internal struct SP_DEVINFO_DATA
6.38 + {
6.39 + internal Int32 cbSize;
6.40 + internal Guid ClassGuid;
6.41 + internal Int32 DevInst;
6.42 + internal Int32 Reserved;
6.43 + }
6.44 +
6.45 + [DllImport("setupapi.dll", SetLastError = true)]
6.46 + internal static extern IntPtr SetupDiCreateDeviceInfoList(ref Guid ClassGuid, IntPtr hwndParent);
6.47 +
6.48 + [DllImport("setupapi.dll", SetLastError = true)]
6.49 + internal static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
6.50 +
6.51 + [DllImport("setupapi.dll", SetLastError = true)]
6.52 + internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
6.53 +
6.54 + [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
6.55 + internal static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags);
6.56 +
6.57 + [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
6.58 + internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData);
6.59 + }
6.60 + }
6.61 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/FileIODeclarations.cs Wed May 14 07:52:21 2014 +0200
7.3 @@ -0,0 +1,23 @@
7.4 +using Microsoft.Win32.SafeHandles;
7.5 +using System.Runtime.InteropServices;
7.6 +using System;
7.7 +
7.8 +namespace GenericHid
7.9 +{
7.10 + /// <summary>
7.11 + /// Win32 API declarations relating to file I/O.
7.12 + /// </summary>
7.13 + ///
7.14 + internal sealed class FileIo
7.15 + {
7.16 + internal const Int32 FileShareRead = 1;
7.17 + internal const Int32 FileShareWrite = 2;
7.18 + internal const uint GenericRead = 0X80000000U;
7.19 + internal const Int32 GenericWrite = 0X40000000;
7.20 + internal const Int32 InvalidHandleValue = -1;
7.21 + internal const Int32 OpenExisting = 3;
7.22 +
7.23 + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
7.24 + internal static extern SafeFileHandle CreateFile(String lpFileName, UInt32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, IntPtr hTemplateFile);
7.25 + }
7.26 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/FrmMain.cs Wed May 14 07:52:21 2014 +0200
8.3 @@ -0,0 +1,2582 @@
8.4 +using Microsoft.Win32.SafeHandles;
8.5 +using System;
8.6 +using System.Diagnostics;
8.7 +using System.Globalization;
8.8 +using System.IO;
8.9 +using System.Management;
8.10 +using System.Runtime.InteropServices;
8.11 +using System.Threading;
8.12 +using System.Timers;
8.13 +using System.Windows.Forms;
8.14 +
8.15 +namespace GenericHid
8.16 +{
8.17 + ///<summary>
8.18 + /// Project: GenericHid
8.19 + ///
8.20 + /// ***********************************************************************
8.21 + /// Software License Agreement
8.22 + ///
8.23 + /// Licensor grants any person obtaining a copy of this software ("You")
8.24 + /// a worldwide, royalty-free, non-exclusive license, for the duration of
8.25 + /// the copyright, free of charge, to store and execute the Software in a
8.26 + /// computer system and to incorporate the Software or any portion of it
8.27 + /// in computer programs You write.
8.28 + ///
8.29 + /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8.30 + /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8.31 + /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8.32 + /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8.33 + /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8.34 + /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
8.35 + /// THE SOFTWARE.
8.36 + /// ***********************************************************************
8.37 + ///
8.38 + /// Author
8.39 + /// Jan Axelson
8.40 + ///
8.41 + /// This software was written using Visual Studio Express 2012 for Windows
8.42 + /// Desktop building for the .NET Framework v4.5.
8.43 + ///
8.44 + /// Purpose:
8.45 + /// Demonstrates USB communications with a generic HID-class device
8.46 + ///
8.47 + /// Requirements:
8.48 + /// Windows Vista or later and an attached USB generic Human Interface Device (HID).
8.49 + /// (Does not run on Windows XP or earlier because .NET Framework 4.5 will not install on these OSes.)
8.50 + ///
8.51 + /// Description:
8.52 + /// Finds an attached device that matches the vendor and product IDs in the form's
8.53 + /// text boxes.
8.54 + ///
8.55 + /// Retrieves the device's capabilities.
8.56 + /// Sends and requests HID reports.
8.57 + ///
8.58 + /// Uses the System.Management class and Windows Management Instrumentation (WMI) to detect
8.59 + /// when a device is attached or removed.
8.60 + ///
8.61 + /// A list box displays the data sent and received along with error and status messages.
8.62 + /// You can select data to send and 1-time or periodic transfers.
8.63 + ///
8.64 + /// You can change the size of the host's Input report buffer and request to use control
8.65 + /// transfers only to exchange Input and Output reports.
8.66 + ///
8.67 + /// To view additional debugging messages, in the Visual Studio development environment,
8.68 + /// from the main menu, select Build > Configuration Manager > Active Solution Configuration
8.69 + /// and select Configuration > Debug and from the main menu, select View > Output.
8.70 + ///
8.71 + /// The application uses asynchronous FileStreams to read Input reports and write Output
8.72 + /// reports so the application's main thread doesn't have to wait for the device to retrieve a
8.73 + /// report when the HID driver's buffer is empty or send a report when the device's endpoint is busy.
8.74 + ///
8.75 + /// For code that finds a device and opens handles to it, see the FindTheHid routine in frmMain.cs.
8.76 + /// For code that reads from the device, see GetInputReportViaInterruptTransfer,
8.77 + /// GetInputReportViaControlTransfer, and GetFeatureReport in Hid.cs.
8.78 + /// For code that writes to the device, see SendInputReportViaInterruptTransfer,
8.79 + /// SendInputReportViaControlTransfer, and SendFeatureReport in Hid.cs.
8.80 + ///
8.81 + /// This project includes the following modules:
8.82 + ///
8.83 + /// GenericHid.cs - runs the application.
8.84 + /// FrmMain.cs - routines specific to the form.
8.85 + /// Hid.cs - routines specific to HID communications.
8.86 + /// DeviceManagement.cs - routine for obtaining a handle to a device from its GUID.
8.87 + /// Debugging.cs - contains a routine for displaying API error messages.
8.88 + /// HidDeclarations.cs - Declarations for API functions used by Hid.cs.
8.89 + /// FileIODeclarations.cs - Declarations for file-related API functions.
8.90 + /// DeviceManagementDeclarations.cs - Declarations for API functions used by DeviceManagement.cs.
8.91 + /// DebuggingDeclarations.cs - Declarations for API functions used by Debugging.cs.
8.92 + ///
8.93 + /// Companion device firmware for several device CPUs is available from www.Lvr.com/hidpage.htm
8.94 + /// You can use any generic HID (not a system mouse or keyboard) that sends and receives reports.
8.95 + /// This application will not detect or communicate with non-HID-class devices.
8.96 + ///
8.97 + /// For more information about HIDs and USB, and additional example device firmware to use
8.98 + /// with this application, visit Lakeview Research at http://Lvr.com
8.99 + /// Send comments, bug reports, etc. to jan@Lvr.com or post on my PORTS forum: http://www.lvr.com/forum
8.100 + ///
8.101 + /// V6.2
8.102 + /// 11/12/13
8.103 + /// Disabled form buttons when a transfer is in progress.
8.104 + /// Other minor edits for clarity and readability.
8.105 + /// Will NOT run on Windows XP or earlier, see below.
8.106 + ///
8.107 + /// V6.1
8.108 + /// 10/28/13
8.109 + /// Uses the .NET System.Management class to detect device arrival and removal with WMI instead of Win32 RegisterDeviceNotification.
8.110 + /// Other minor edits.
8.111 + /// Will NOT run on Windows XP or earlier, see below.
8.112 + ///
8.113 + /// V6.0
8.114 + /// 2/8/13
8.115 + /// This version will NOT run on Windows XP or earlier because the code uses .NET Framework 4.5 to support asynchronous FileStreams.
8.116 + /// The .NET Framework 4.5 redistributable is compatible with Windows 8, Windows 7 SP1, Windows Server 2008 R2 SP1,
8.117 + /// Windows Server 2008 SP2, Windows Vista SP2, and Windows Vista SP3.
8.118 + /// For compatibility, replaced ToInt32 with ToInt64 here:
8.119 + /// IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
8.120 + /// and here:
8.121 + /// if ((deviceNotificationHandle.ToInt64() == IntPtr.Zero.ToInt64()))
8.122 + /// For compatibility if the charset isn't English, added System.Globalization.CultureInfo.InvariantCulture here:
8.123 + /// if ((String.Compare(DeviceNameString, mydevicePathName, true, System.Globalization.CultureInfo.InvariantCulture) == 0))
8.124 + /// Replaced all Microsoft.VisualBasic namespace code with other .NET equivalents.
8.125 + /// Revised user interface for more flexibility.
8.126 + /// Moved interrupt-transfer and other HID-specific code to Hid.cs.
8.127 + /// Used JetBrains ReSharper to clean up the code: http://www.jetbrains.com/resharper/
8.128 + ///
8.129 + /// V5.0
8.130 + /// 3/30/11
8.131 + /// Replaced ReadFile and WriteFile with FileStreams. Thanks to Joe Dunne and John on my Ports forum for tips on this.
8.132 + /// Simplified Hid.cs.
8.133 + /// Replaced the form timer with a system timer.
8.134 + ///
8.135 + /// V4.6
8.136 + /// 1/12/10
8.137 + /// Supports Vendor IDs and Product IDs up to FFFFh.
8.138 + ///
8.139 + /// V4.52
8.140 + /// 11/10/09
8.141 + /// Changed HIDD_ATTRIBUTES to use UInt16
8.142 + ///
8.143 + /// V4.51
8.144 + /// 2/11/09
8.145 + /// Moved Free_ and similar to Finally blocks to ensure they execute.
8.146 + ///
8.147 + /// V4.5
8.148 + /// 2/9/09
8.149 + /// Changes to support 64-bit systems, memory management, and other corrections.
8.150 + /// Big thanks to Peter Nielsen.
8.151 + ///
8.152 + /// </summary>
8.153 +
8.154 + internal class FrmMain
8.155 + : Form
8.156 + {
8.157 + #region '"Windows Form Designer generated code "'
8.158 + public FrmMain()
8.159 + //: base()
8.160 + {
8.161 + // This call is required by the Windows Form Designer.
8.162 + InitializeComponent();
8.163 + }
8.164 + // Form overrides dispose to clean up the component list.
8.165 + protected override void Dispose(bool Disposing1)
8.166 + {
8.167 + if (Disposing1)
8.168 + {
8.169 + if (components != null)
8.170 + {
8.171 + components.Dispose();
8.172 + }
8.173 + }
8.174 + base.Dispose(Disposing1);
8.175 + }
8.176 +
8.177 + // Required by the Windows Form Designer
8.178 + private System.ComponentModel.IContainer components;
8.179 + public System.Windows.Forms.ToolTip ToolTip1;
8.180 + public System.Windows.Forms.TextBox TxtBytesReceived;
8.181 + public System.Windows.Forms.GroupBox FraBytesReceived;
8.182 + public System.Windows.Forms.CheckBox ChkAutoincrement;
8.183 + public System.Windows.Forms.ComboBox CboByte1;
8.184 + public System.Windows.Forms.ComboBox CboByte0;
8.185 + public System.Windows.Forms.GroupBox FraBytesToSend;
8.186 + public System.Windows.Forms.ListBox LstResults;
8.187 + // NOTE: The following procedure is required by the Windows Form Designer
8.188 + // It can be modified using the Windows Form Designer.
8.189 + // Do not modify it using the code editor.
8.190 + internal System.Windows.Forms.GroupBox fraInputReportBufferSize;
8.191 + internal System.Windows.Forms.TextBox txtInputReportBufferSize;
8.192 + internal System.Windows.Forms.Button cmdInputReportBufferSize;
8.193 + internal System.Windows.Forms.GroupBox fraDeviceIdentifiers;
8.194 + internal System.Windows.Forms.Label lblVendorID;
8.195 + internal System.Windows.Forms.TextBox txtVendorID;
8.196 + internal System.Windows.Forms.Label lblProductID;
8.197 + internal System.Windows.Forms.TextBox txtProductID;
8.198 + internal System.Windows.Forms.Button cmdFindDevice;
8.199 + private Button cmdGetInputReportInterrupt;
8.200 + public GroupBox fraInterruptTransfers;
8.201 + private Button cmdSendOutputReportControl;
8.202 + private Button cmdGetInputReportControl;
8.203 + public GroupBox fraControlTransfers;
8.204 + private Button cmdGetFeatureReport;
8.205 + private Button cmdSendFeatureReport;
8.206 + private Button cmdPeriodicTransfers;
8.207 + public GroupBox fraSendAndGetContinuous;
8.208 + private RadioButton radFeature;
8.209 + private RadioButton radInputOutputControl;
8.210 + private RadioButton radInputOutputInterrupt;
8.211 + private Button cmdSendOutputReportInterrupt;
8.212 +
8.213 + [System.Diagnostics.DebuggerStepThrough()]
8.214 + private void InitializeComponent()
8.215 + {
8.216 + this.components = new System.ComponentModel.Container();
8.217 + this.ToolTip1 = new System.Windows.Forms.ToolTip(this.components);
8.218 + this.FraBytesReceived = new System.Windows.Forms.GroupBox();
8.219 + this.TxtBytesReceived = new System.Windows.Forms.TextBox();
8.220 + this.FraBytesToSend = new System.Windows.Forms.GroupBox();
8.221 + this.ChkAutoincrement = new System.Windows.Forms.CheckBox();
8.222 + this.CboByte1 = new System.Windows.Forms.ComboBox();
8.223 + this.CboByte0 = new System.Windows.Forms.ComboBox();
8.224 + this.LstResults = new System.Windows.Forms.ListBox();
8.225 + this.fraInputReportBufferSize = new System.Windows.Forms.GroupBox();
8.226 + this.cmdInputReportBufferSize = new System.Windows.Forms.Button();
8.227 + this.txtInputReportBufferSize = new System.Windows.Forms.TextBox();
8.228 + this.fraDeviceIdentifiers = new System.Windows.Forms.GroupBox();
8.229 + this.txtProductID = new System.Windows.Forms.TextBox();
8.230 + this.lblProductID = new System.Windows.Forms.Label();
8.231 + this.txtVendorID = new System.Windows.Forms.TextBox();
8.232 + this.lblVendorID = new System.Windows.Forms.Label();
8.233 + this.cmdFindDevice = new System.Windows.Forms.Button();
8.234 + this.cmdSendOutputReportInterrupt = new System.Windows.Forms.Button();
8.235 + this.cmdGetInputReportInterrupt = new System.Windows.Forms.Button();
8.236 + this.fraInterruptTransfers = new System.Windows.Forms.GroupBox();
8.237 + this.cmdPeriodicTransfers = new System.Windows.Forms.Button();
8.238 + this.cmdSendOutputReportControl = new System.Windows.Forms.Button();
8.239 + this.cmdGetInputReportControl = new System.Windows.Forms.Button();
8.240 + this.fraControlTransfers = new System.Windows.Forms.GroupBox();
8.241 + this.cmdGetFeatureReport = new System.Windows.Forms.Button();
8.242 + this.cmdSendFeatureReport = new System.Windows.Forms.Button();
8.243 + this.fraSendAndGetContinuous = new System.Windows.Forms.GroupBox();
8.244 + this.radInputOutputInterrupt = new System.Windows.Forms.RadioButton();
8.245 + this.radInputOutputControl = new System.Windows.Forms.RadioButton();
8.246 + this.radFeature = new System.Windows.Forms.RadioButton();
8.247 + this.FraBytesReceived.SuspendLayout();
8.248 + this.FraBytesToSend.SuspendLayout();
8.249 + this.fraInputReportBufferSize.SuspendLayout();
8.250 + this.fraDeviceIdentifiers.SuspendLayout();
8.251 + this.fraInterruptTransfers.SuspendLayout();
8.252 + this.fraControlTransfers.SuspendLayout();
8.253 + this.fraSendAndGetContinuous.SuspendLayout();
8.254 + this.SuspendLayout();
8.255 + //
8.256 + // fraBytesReceived
8.257 + //
8.258 + this.FraBytesReceived.BackColor = System.Drawing.SystemColors.Control;
8.259 + this.FraBytesReceived.Controls.Add(this.TxtBytesReceived);
8.260 + this.FraBytesReceived.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.261 + this.FraBytesReceived.ForeColor = System.Drawing.SystemColors.ControlText;
8.262 + this.FraBytesReceived.Location = new System.Drawing.Point(16, 272);
8.263 + this.FraBytesReceived.Name = "FraBytesReceived";
8.264 + this.FraBytesReceived.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.265 + this.FraBytesReceived.Size = new System.Drawing.Size(112, 136);
8.266 + this.FraBytesReceived.TabIndex = 4;
8.267 + this.FraBytesReceived.TabStop = false;
8.268 + this.FraBytesReceived.Text = "Bytes Received";
8.269 + //
8.270 + // txtBytesReceived
8.271 + //
8.272 + this.TxtBytesReceived.AcceptsReturn = true;
8.273 + this.TxtBytesReceived.BackColor = System.Drawing.SystemColors.Window;
8.274 + this.TxtBytesReceived.Cursor = System.Windows.Forms.Cursors.IBeam;
8.275 + this.TxtBytesReceived.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.276 + this.TxtBytesReceived.ForeColor = System.Drawing.SystemColors.WindowText;
8.277 + this.TxtBytesReceived.Location = new System.Drawing.Point(18, 24);
8.278 + this.TxtBytesReceived.MaxLength = 0;
8.279 + this.TxtBytesReceived.Multiline = true;
8.280 + this.TxtBytesReceived.Name = "TxtBytesReceived";
8.281 + this.TxtBytesReceived.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.282 + this.TxtBytesReceived.Size = new System.Drawing.Size(72, 96);
8.283 + this.TxtBytesReceived.TabIndex = 5;
8.284 + //
8.285 + // fraBytesToSend
8.286 + //
8.287 + this.FraBytesToSend.BackColor = System.Drawing.SystemColors.Control;
8.288 + this.FraBytesToSend.Controls.Add(this.ChkAutoincrement);
8.289 + this.FraBytesToSend.Controls.Add(this.CboByte1);
8.290 + this.FraBytesToSend.Controls.Add(this.CboByte0);
8.291 + this.FraBytesToSend.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.292 + this.FraBytesToSend.ForeColor = System.Drawing.SystemColors.ControlText;
8.293 + this.FraBytesToSend.Location = new System.Drawing.Point(16, 128);
8.294 + this.FraBytesToSend.Name = "FraBytesToSend";
8.295 + this.FraBytesToSend.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.296 + this.FraBytesToSend.Size = new System.Drawing.Size(160, 136);
8.297 + this.FraBytesToSend.TabIndex = 1;
8.298 + this.FraBytesToSend.TabStop = false;
8.299 + this.FraBytesToSend.Text = "Bytes to Send";
8.300 + //
8.301 + // chkAutoincrement
8.302 + //
8.303 + this.ChkAutoincrement.BackColor = System.Drawing.SystemColors.Control;
8.304 + this.ChkAutoincrement.Cursor = System.Windows.Forms.Cursors.Default;
8.305 + this.ChkAutoincrement.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.306 + this.ChkAutoincrement.ForeColor = System.Drawing.SystemColors.ControlText;
8.307 + this.ChkAutoincrement.Location = new System.Drawing.Point(8, 96);
8.308 + this.ChkAutoincrement.Name = "ChkAutoincrement";
8.309 + this.ChkAutoincrement.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.310 + this.ChkAutoincrement.Size = new System.Drawing.Size(201, 35);
8.311 + this.ChkAutoincrement.TabIndex = 6;
8.312 + this.ChkAutoincrement.Text = "Autoincrement values";
8.313 + this.ChkAutoincrement.UseVisualStyleBackColor = false;
8.314 + //
8.315 + // cboByte1
8.316 + //
8.317 + this.CboByte1.BackColor = System.Drawing.SystemColors.Window;
8.318 + this.CboByte1.Cursor = System.Windows.Forms.Cursors.Default;
8.319 + this.CboByte1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
8.320 + this.CboByte1.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.321 + this.CboByte1.ForeColor = System.Drawing.SystemColors.WindowText;
8.322 + this.CboByte1.Location = new System.Drawing.Point(8, 64);
8.323 + this.CboByte1.Name = "CboByte1";
8.324 + this.CboByte1.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.325 + this.CboByte1.Size = new System.Drawing.Size(101, 22);
8.326 + this.CboByte1.TabIndex = 3;
8.327 + //
8.328 + // cboByte0
8.329 + //
8.330 + this.CboByte0.BackColor = System.Drawing.SystemColors.Window;
8.331 + this.CboByte0.Cursor = System.Windows.Forms.Cursors.Default;
8.332 + this.CboByte0.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
8.333 + this.CboByte0.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.334 + this.CboByte0.ForeColor = System.Drawing.SystemColors.WindowText;
8.335 + this.CboByte0.Location = new System.Drawing.Point(8, 24);
8.336 + this.CboByte0.Name = "CboByte0";
8.337 + this.CboByte0.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.338 + this.CboByte0.Size = new System.Drawing.Size(101, 22);
8.339 + this.CboByte0.TabIndex = 2;
8.340 + //
8.341 + // lstResults
8.342 + //
8.343 + this.LstResults.BackColor = System.Drawing.SystemColors.Window;
8.344 + this.LstResults.Cursor = System.Windows.Forms.Cursors.Default;
8.345 + this.LstResults.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.346 + this.LstResults.ForeColor = System.Drawing.SystemColors.WindowText;
8.347 + this.LstResults.HorizontalScrollbar = true;
8.348 + this.LstResults.ItemHeight = 14;
8.349 + this.LstResults.Location = new System.Drawing.Point(12, 424);
8.350 + this.LstResults.Name = "LstResults";
8.351 + this.LstResults.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.352 + this.LstResults.Size = new System.Drawing.Size(760, 326);
8.353 + this.LstResults.TabIndex = 0;
8.354 + //
8.355 + // fraInputReportBufferSize
8.356 + //
8.357 + this.fraInputReportBufferSize.Controls.Add(this.cmdInputReportBufferSize);
8.358 + this.fraInputReportBufferSize.Controls.Add(this.txtInputReportBufferSize);
8.359 + this.fraInputReportBufferSize.Location = new System.Drawing.Point(248, 16);
8.360 + this.fraInputReportBufferSize.Name = "fraInputReportBufferSize";
8.361 + this.fraInputReportBufferSize.Size = new System.Drawing.Size(208, 96);
8.362 + this.fraInputReportBufferSize.TabIndex = 9;
8.363 + this.fraInputReportBufferSize.TabStop = false;
8.364 + this.fraInputReportBufferSize.Text = "Input Report Buffer Size";
8.365 + //
8.366 + // cmdInputReportBufferSize
8.367 + //
8.368 + this.cmdInputReportBufferSize.Location = new System.Drawing.Point(96, 32);
8.369 + this.cmdInputReportBufferSize.Name = "cmdInputReportBufferSize";
8.370 + this.cmdInputReportBufferSize.Size = new System.Drawing.Size(96, 56);
8.371 + this.cmdInputReportBufferSize.TabIndex = 1;
8.372 + this.cmdInputReportBufferSize.Text = "Change Buffer Size";
8.373 + this.cmdInputReportBufferSize.Click += new System.EventHandler(this.cmdInputReportBufferSize_Click);
8.374 + //
8.375 + // txtInputReportBufferSize
8.376 + //
8.377 + this.txtInputReportBufferSize.Location = new System.Drawing.Point(16, 40);
8.378 + this.txtInputReportBufferSize.Name = "txtInputReportBufferSize";
8.379 + this.txtInputReportBufferSize.Size = new System.Drawing.Size(56, 20);
8.380 + this.txtInputReportBufferSize.TabIndex = 0;
8.381 + //
8.382 + // fraDeviceIdentifiers
8.383 + //
8.384 + this.fraDeviceIdentifiers.Controls.Add(this.txtProductID);
8.385 + this.fraDeviceIdentifiers.Controls.Add(this.lblProductID);
8.386 + this.fraDeviceIdentifiers.Controls.Add(this.txtVendorID);
8.387 + this.fraDeviceIdentifiers.Controls.Add(this.lblVendorID);
8.388 + this.fraDeviceIdentifiers.Location = new System.Drawing.Point(16, 16);
8.389 + this.fraDeviceIdentifiers.Name = "fraDeviceIdentifiers";
8.390 + this.fraDeviceIdentifiers.Size = new System.Drawing.Size(208, 96);
8.391 + this.fraDeviceIdentifiers.TabIndex = 10;
8.392 + this.fraDeviceIdentifiers.TabStop = false;
8.393 + this.fraDeviceIdentifiers.Text = "Device Identifiers";
8.394 + //
8.395 + // txtProductID
8.396 + //
8.397 + this.txtProductID.Location = new System.Drawing.Point(120, 56);
8.398 + this.txtProductID.Name = "txtProductID";
8.399 + this.txtProductID.Size = new System.Drawing.Size(72, 20);
8.400 + this.txtProductID.TabIndex = 3;
8.401 + this.txtProductID.Text = "1299";
8.402 + this.txtProductID.TextChanged += new System.EventHandler(this.txtProductID_TextChanged);
8.403 + //
8.404 + // lblProductID
8.405 + //
8.406 + this.lblProductID.Location = new System.Drawing.Point(16, 56);
8.407 + this.lblProductID.Name = "lblProductID";
8.408 + this.lblProductID.Size = new System.Drawing.Size(112, 23);
8.409 + this.lblProductID.TabIndex = 2;
8.410 + this.lblProductID.Text = "Product ID (hex):";
8.411 + //
8.412 + // txtVendorID
8.413 + //
8.414 + this.txtVendorID.Location = new System.Drawing.Point(120, 24);
8.415 + this.txtVendorID.Name = "txtVendorID";
8.416 + this.txtVendorID.Size = new System.Drawing.Size(72, 20);
8.417 + this.txtVendorID.TabIndex = 1;
8.418 + this.txtVendorID.Text = "0925";
8.419 + this.txtVendorID.TextChanged += new System.EventHandler(this.txtVendorID_TextChanged);
8.420 + //
8.421 + // lblVendorID
8.422 + //
8.423 + this.lblVendorID.Location = new System.Drawing.Point(16, 24);
8.424 + this.lblVendorID.Name = "lblVendorID";
8.425 + this.lblVendorID.Size = new System.Drawing.Size(112, 23);
8.426 + this.lblVendorID.TabIndex = 0;
8.427 + this.lblVendorID.Text = "Vendor ID (hex):";
8.428 + //
8.429 + // cmdFindDevice
8.430 + //
8.431 + this.cmdFindDevice.Location = new System.Drawing.Point(483, 37);
8.432 + this.cmdFindDevice.Name = "cmdFindDevice";
8.433 + this.cmdFindDevice.Size = new System.Drawing.Size(136, 55);
8.434 + this.cmdFindDevice.TabIndex = 11;
8.435 + this.cmdFindDevice.Text = "Find My Device";
8.436 + this.cmdFindDevice.Click += new System.EventHandler(this.cmdFindDevice_Click);
8.437 + //
8.438 + // cmdSendOutputReportInterrupt
8.439 + //
8.440 + this.cmdSendOutputReportInterrupt.Location = new System.Drawing.Point(10, 27);
8.441 + this.cmdSendOutputReportInterrupt.Name = "cmdSendOutputReportInterrupt";
8.442 + this.cmdSendOutputReportInterrupt.Size = new System.Drawing.Size(118, 50);
8.443 + this.cmdSendOutputReportInterrupt.TabIndex = 12;
8.444 + this.cmdSendOutputReportInterrupt.Text = "Send Output Report";
8.445 + this.cmdSendOutputReportInterrupt.UseVisualStyleBackColor = true;
8.446 + this.cmdSendOutputReportInterrupt.Click += new System.EventHandler(this.cmdSendOutputReportInterrupt_Click);
8.447 + //
8.448 + // cmdGetInputReportInterrupt
8.449 + //
8.450 + this.cmdGetInputReportInterrupt.Location = new System.Drawing.Point(10, 83);
8.451 + this.cmdGetInputReportInterrupt.Name = "cmdGetInputReportInterrupt";
8.452 + this.cmdGetInputReportInterrupt.Size = new System.Drawing.Size(118, 50);
8.453 + this.cmdGetInputReportInterrupt.TabIndex = 13;
8.454 + this.cmdGetInputReportInterrupt.Text = "Get Input Report";
8.455 + this.cmdGetInputReportInterrupt.UseVisualStyleBackColor = true;
8.456 + this.cmdGetInputReportInterrupt.Click += new System.EventHandler(this.cmdGetInputReportInterrupt_Click);
8.457 + //
8.458 + // fraInterruptTransfers
8.459 + //
8.460 + this.fraInterruptTransfers.BackColor = System.Drawing.SystemColors.Control;
8.461 + this.fraInterruptTransfers.Controls.Add(this.cmdSendOutputReportInterrupt);
8.462 + this.fraInterruptTransfers.Controls.Add(this.cmdGetInputReportInterrupt);
8.463 + this.fraInterruptTransfers.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.464 + this.fraInterruptTransfers.ForeColor = System.Drawing.SystemColors.ControlText;
8.465 + this.fraInterruptTransfers.Location = new System.Drawing.Point(194, 128);
8.466 + this.fraInterruptTransfers.Name = "fraInterruptTransfers";
8.467 + this.fraInterruptTransfers.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.468 + this.fraInterruptTransfers.Size = new System.Drawing.Size(145, 152);
8.469 + this.fraInterruptTransfers.TabIndex = 14;
8.470 + this.fraInterruptTransfers.TabStop = false;
8.471 + this.fraInterruptTransfers.Text = "Interrupt Transfers";
8.472 + //
8.473 + // cmdPeriodicTransfers
8.474 + //
8.475 + this.cmdPeriodicTransfers.Location = new System.Drawing.Point(153, 36);
8.476 + this.cmdPeriodicTransfers.Name = "cmdPeriodicTransfers";
8.477 + this.cmdPeriodicTransfers.Size = new System.Drawing.Size(118, 51);
8.478 + this.cmdPeriodicTransfers.TabIndex = 16;
8.479 + this.cmdPeriodicTransfers.Text = "Start";
8.480 + this.cmdPeriodicTransfers.UseVisualStyleBackColor = true;
8.481 + this.cmdPeriodicTransfers.Click += new System.EventHandler(this.cmdPeriodicTransfers_Click);
8.482 + //
8.483 + // cmdSendOutputReportControl
8.484 + //
8.485 + this.cmdSendOutputReportControl.Location = new System.Drawing.Point(10, 27);
8.486 + this.cmdSendOutputReportControl.Name = "cmdSendOutputReportControl";
8.487 + this.cmdSendOutputReportControl.Size = new System.Drawing.Size(118, 50);
8.488 + this.cmdSendOutputReportControl.TabIndex = 12;
8.489 + this.cmdSendOutputReportControl.Text = "Send Output Report";
8.490 + this.cmdSendOutputReportControl.UseVisualStyleBackColor = true;
8.491 + this.cmdSendOutputReportControl.Click += new System.EventHandler(this.cmdSendOutputReportControl_Click);
8.492 + //
8.493 + // cmdGetInputReportControl
8.494 + //
8.495 + this.cmdGetInputReportControl.Location = new System.Drawing.Point(10, 83);
8.496 + this.cmdGetInputReportControl.Name = "cmdGetInputReportControl";
8.497 + this.cmdGetInputReportControl.Size = new System.Drawing.Size(118, 50);
8.498 + this.cmdGetInputReportControl.TabIndex = 13;
8.499 + this.cmdGetInputReportControl.Text = "Get Input Report";
8.500 + this.cmdGetInputReportControl.UseVisualStyleBackColor = true;
8.501 + this.cmdGetInputReportControl.Click += new System.EventHandler(this.cmdGetInputReportControl_Click);
8.502 + //
8.503 + // fraControlTransfers
8.504 + //
8.505 + this.fraControlTransfers.BackColor = System.Drawing.SystemColors.Control;
8.506 + this.fraControlTransfers.Controls.Add(this.cmdGetFeatureReport);
8.507 + this.fraControlTransfers.Controls.Add(this.cmdSendFeatureReport);
8.508 + this.fraControlTransfers.Controls.Add(this.cmdSendOutputReportControl);
8.509 + this.fraControlTransfers.Controls.Add(this.cmdGetInputReportControl);
8.510 + this.fraControlTransfers.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.511 + this.fraControlTransfers.ForeColor = System.Drawing.SystemColors.ControlText;
8.512 + this.fraControlTransfers.Location = new System.Drawing.Point(359, 128);
8.513 + this.fraControlTransfers.Name = "fraControlTransfers";
8.514 + this.fraControlTransfers.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.515 + this.fraControlTransfers.Size = new System.Drawing.Size(277, 152);
8.516 + this.fraControlTransfers.TabIndex = 15;
8.517 + this.fraControlTransfers.TabStop = false;
8.518 + this.fraControlTransfers.Text = "Control Transfers";
8.519 + //
8.520 + // cmdGetFeatureReport
8.521 + //
8.522 + this.cmdGetFeatureReport.Location = new System.Drawing.Point(141, 83);
8.523 + this.cmdGetFeatureReport.Name = "cmdGetFeatureReport";
8.524 + this.cmdGetFeatureReport.Size = new System.Drawing.Size(118, 50);
8.525 + this.cmdGetFeatureReport.TabIndex = 15;
8.526 + this.cmdGetFeatureReport.Text = "Get Feature Report";
8.527 + this.cmdGetFeatureReport.UseVisualStyleBackColor = true;
8.528 + this.cmdGetFeatureReport.Click += new System.EventHandler(this.cmdGetFeatureReport_Click);
8.529 + //
8.530 + // cmdSendFeatureReport
8.531 + //
8.532 + this.cmdSendFeatureReport.Location = new System.Drawing.Point(141, 27);
8.533 + this.cmdSendFeatureReport.Name = "cmdSendFeatureReport";
8.534 + this.cmdSendFeatureReport.Size = new System.Drawing.Size(118, 50);
8.535 + this.cmdSendFeatureReport.TabIndex = 14;
8.536 + this.cmdSendFeatureReport.Text = "Send Feature Report";
8.537 + this.cmdSendFeatureReport.UseVisualStyleBackColor = true;
8.538 + this.cmdSendFeatureReport.Click += new System.EventHandler(this.cmdSendFeatureReport_Click);
8.539 + //
8.540 + // fraSendAndGetContinuous
8.541 + //
8.542 + this.fraSendAndGetContinuous.BackColor = System.Drawing.SystemColors.Control;
8.543 + this.fraSendAndGetContinuous.Controls.Add(this.radFeature);
8.544 + this.fraSendAndGetContinuous.Controls.Add(this.radInputOutputControl);
8.545 + this.fraSendAndGetContinuous.Controls.Add(this.radInputOutputInterrupt);
8.546 + this.fraSendAndGetContinuous.Controls.Add(this.cmdPeriodicTransfers);
8.547 + this.fraSendAndGetContinuous.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.548 + this.fraSendAndGetContinuous.ForeColor = System.Drawing.SystemColors.ControlText;
8.549 + this.fraSendAndGetContinuous.Location = new System.Drawing.Point(194, 296);
8.550 + this.fraSendAndGetContinuous.Name = "fraSendAndGetContinuous";
8.551 + this.fraSendAndGetContinuous.RightToLeft = System.Windows.Forms.RightToLeft.No;
8.552 + this.fraSendAndGetContinuous.Size = new System.Drawing.Size(295, 112);
8.553 + this.fraSendAndGetContinuous.TabIndex = 17;
8.554 + this.fraSendAndGetContinuous.TabStop = false;
8.555 + this.fraSendAndGetContinuous.Text = "Send and Get Continuous";
8.556 + //
8.557 + // radInputOutputInterrupt
8.558 + //
8.559 + this.radInputOutputInterrupt.AutoSize = true;
8.560 + this.radInputOutputInterrupt.Location = new System.Drawing.Point(17, 28);
8.561 + this.radInputOutputInterrupt.Name = "radInputOutputInterrupt";
8.562 + this.radInputOutputInterrupt.Size = new System.Drawing.Size(126, 18);
8.563 + this.radInputOutputInterrupt.TabIndex = 17;
8.564 + this.radInputOutputInterrupt.TabStop = true;
8.565 + this.radInputOutputInterrupt.Text = "Input Output Interrupt";
8.566 + this.radInputOutputInterrupt.UseVisualStyleBackColor = true;
8.567 + this.radInputOutputInterrupt.CheckedChanged += new System.EventHandler(this.radInputOutputInterrupt_CheckedChanged);
8.568 + //
8.569 + // radInputOutputControl
8.570 + //
8.571 + this.radInputOutputControl.AutoSize = true;
8.572 + this.radInputOutputControl.Location = new System.Drawing.Point(17, 52);
8.573 + this.radInputOutputControl.Name = "radInputOutputControl";
8.574 + this.radInputOutputControl.Size = new System.Drawing.Size(120, 18);
8.575 + this.radInputOutputControl.TabIndex = 18;
8.576 + this.radInputOutputControl.TabStop = true;
8.577 + this.radInputOutputControl.Text = "Input Output Control";
8.578 + this.radInputOutputControl.UseVisualStyleBackColor = true;
8.579 + this.radInputOutputControl.CheckedChanged += new System.EventHandler(this.radInputOutputControl_CheckedChanged);
8.580 + //
8.581 + // radFeature
8.582 + //
8.583 + this.radFeature.AutoSize = true;
8.584 + this.radFeature.Location = new System.Drawing.Point(17, 76);
8.585 + this.radFeature.Name = "radFeature";
8.586 + this.radFeature.Size = new System.Drawing.Size(62, 18);
8.587 + this.radFeature.TabIndex = 19;
8.588 + this.radFeature.TabStop = true;
8.589 + this.radFeature.Text = "Feature";
8.590 + this.radFeature.UseVisualStyleBackColor = true;
8.591 + this.radFeature.CheckedChanged += new System.EventHandler(this.radFeature_CheckedChanged);
8.592 + //
8.593 + // FrmMain
8.594 + //
8.595 + this.ClientSize = new System.Drawing.Size(784, 756);
8.596 + this.Controls.Add(this.fraSendAndGetContinuous);
8.597 + this.Controls.Add(this.fraControlTransfers);
8.598 + this.Controls.Add(this.fraInterruptTransfers);
8.599 + this.Controls.Add(this.cmdFindDevice);
8.600 + this.Controls.Add(this.fraDeviceIdentifiers);
8.601 + this.Controls.Add(this.fraInputReportBufferSize);
8.602 + this.Controls.Add(this.FraBytesReceived);
8.603 + this.Controls.Add(this.FraBytesToSend);
8.604 + this.Controls.Add(this.LstResults);
8.605 + this.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
8.606 + this.Location = new System.Drawing.Point(21, 28);
8.607 + this.Name = "FrmMain";
8.608 + this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
8.609 + this.Text = "Generic HID Tester";
8.610 + this.Closed += new System.EventHandler(this.frmMain_Closed);
8.611 + this.Load += new System.EventHandler(this.frmMain_Load);
8.612 + this.FraBytesReceived.ResumeLayout(false);
8.613 + this.FraBytesReceived.PerformLayout();
8.614 + this.FraBytesToSend.ResumeLayout(false);
8.615 + this.fraInputReportBufferSize.ResumeLayout(false);
8.616 + this.fraInputReportBufferSize.PerformLayout();
8.617 + this.fraDeviceIdentifiers.ResumeLayout(false);
8.618 + this.fraDeviceIdentifiers.PerformLayout();
8.619 + this.fraInterruptTransfers.ResumeLayout(false);
8.620 + this.fraControlTransfers.ResumeLayout(false);
8.621 + this.fraSendAndGetContinuous.ResumeLayout(false);
8.622 + this.fraSendAndGetContinuous.PerformLayout();
8.623 + this.ResumeLayout(false);
8.624 +
8.625 + }
8.626 + #endregion
8.627 +
8.628 + private Boolean _deviceDetected;
8.629 + private IntPtr _deviceNotificationHandle;
8.630 + private FileStream _deviceData;
8.631 + private FormActions _formActions;
8.632 + private SafeFileHandle _hidHandle;
8.633 + private String _hidUsage;
8.634 + private ManagementEventWatcher _deviceArrivedWatcher;
8.635 + private Boolean _deviceHandleObtained;
8.636 + private ManagementEventWatcher _deviceRemovedWatcher;
8.637 + private Int32 _myProductId;
8.638 + private Int32 _myVendorId;
8.639 + private Boolean _periodicTransfersRequested;
8.640 + private ReportReadOrWritten _readOrWritten;
8.641 + private ReportTypes _reportType;
8.642 + private SendOrGet _sendOrGet;
8.643 + private Boolean _transferInProgress;
8.644 + private TransferTypes _transferType;
8.645 +
8.646 + private static System.Timers.Timer _periodicTransfers;
8.647 +
8.648 + private readonly Debugging _myDebugging = new Debugging(); // For viewing results of API calls via Debug.Write.
8.649 + private readonly DeviceManagement _myDeviceManagement = new DeviceManagement();
8.650 + private Hid _myHid = new Hid();
8.651 +
8.652 + private enum FormActions
8.653 + {
8.654 + AddItemToListBox,
8.655 + DisableInputReportBufferSize,
8.656 + EnableGetInputReportInterruptTransfer,
8.657 + EnableInputReportBufferSize,
8.658 + EnableSendOutputReportInterrupt,
8.659 + ScrollToBottomOfListBox,
8.660 + SetInputReportBufferSize
8.661 + }
8.662 +
8.663 + private enum ReportReadOrWritten
8.664 + {
8.665 + Read,
8.666 + Written
8.667 + }
8.668 +
8.669 + private enum ReportTypes
8.670 + {
8.671 + Input,
8.672 + Output,
8.673 + Feature
8.674 + }
8.675 +
8.676 + private enum SendOrGet
8.677 + {
8.678 + Send,
8.679 + Get
8.680 + }
8.681 +
8.682 + private enum TransferTypes
8.683 + {
8.684 + Control,
8.685 + Interrupt
8.686 + }
8.687 +
8.688 + private enum WmiDeviceProperties
8.689 + {
8.690 + Name,
8.691 + Caption,
8.692 + Description,
8.693 + Manufacturer,
8.694 + PNPDeviceID,
8.695 + DeviceID,
8.696 + ClassGUID
8.697 + }
8.698 +
8.699 + internal FrmMain FrmMy;
8.700 +
8.701 + // This delegate has the same parameters as AccessForm.
8.702 + // Used in accessing the application's form from a different thread.
8.703 +
8.704 + private delegate void MarshalDataToForm(FormActions action, String textToAdd);
8.705 +
8.706 + /// <summary>
8.707 + /// Performs various application-specific functions that
8.708 + /// involve accessing the application's form.
8.709 + /// </summary>
8.710 + ///
8.711 + /// <param name="action"> a FormActions member that names the action to perform on the form</param>
8.712 + /// <param name="formText"> text that the form displays or the code uses for
8.713 + /// another purpose. Actions that don't use text ignore this parameter. </param>
8.714 +
8.715 + private void AccessForm(FormActions action, String formText)
8.716 + {
8.717 + try
8.718 + {
8.719 + // Select an action to perform on the form:
8.720 +
8.721 + switch (action)
8.722 + {
8.723 + case FormActions.AddItemToListBox:
8.724 +
8.725 + LstResults.Items.Add(formText);
8.726 + break;
8.727 +
8.728 + case FormActions.DisableInputReportBufferSize:
8.729 +
8.730 + cmdInputReportBufferSize.Enabled = false;
8.731 + break;
8.732 +
8.733 + case FormActions.EnableGetInputReportInterruptTransfer:
8.734 +
8.735 + cmdGetInputReportInterrupt.Enabled = true;
8.736 + break;
8.737 +
8.738 + case FormActions.EnableInputReportBufferSize:
8.739 +
8.740 + cmdInputReportBufferSize.Enabled = true;
8.741 + break;
8.742 +
8.743 + case FormActions.EnableSendOutputReportInterrupt:
8.744 +
8.745 + cmdSendOutputReportInterrupt.Enabled = true;
8.746 + break;
8.747 +
8.748 + case FormActions.ScrollToBottomOfListBox:
8.749 +
8.750 + LstResults.SelectedIndex = LstResults.Items.Count - 1;
8.751 + break;
8.752 +
8.753 + case FormActions.SetInputReportBufferSize:
8.754 +
8.755 + txtInputReportBufferSize.Text = formText;
8.756 + break;
8.757 + }
8.758 + }
8.759 + catch (Exception ex)
8.760 + {
8.761 + DisplayException(Name, ex);
8.762 + throw;
8.763 + }
8.764 + }
8.765 +
8.766 + /// <summary>
8.767 + /// Add a handler to detect arrival of devices using WMI.
8.768 + /// </summary>
8.769 +
8.770 + private void AddDeviceArrivedHandler()
8.771 + {
8.772 + const Int32 pollingIntervalSeconds = 3;
8.773 + var scope = new ManagementScope("root\\CIMV2");
8.774 + scope.Options.EnablePrivileges = true;
8.775 +
8.776 + try
8.777 + {
8.778 + var q = new WqlEventQuery();
8.779 + q.EventClassName = "__InstanceCreationEvent";
8.780 + q.WithinInterval = new TimeSpan(0, 0, pollingIntervalSeconds);
8.781 + q.Condition = @"TargetInstance ISA 'Win32_USBControllerdevice'";
8.782 + _deviceArrivedWatcher = new ManagementEventWatcher(scope, q);
8.783 + _deviceArrivedWatcher.EventArrived += DeviceAdded;
8.784 +
8.785 + _deviceArrivedWatcher.Start();
8.786 + }
8.787 + catch (Exception e)
8.788 + {
8.789 + Debug.WriteLine(e.Message);
8.790 + if (_deviceArrivedWatcher != null)
8.791 + _deviceArrivedWatcher.Stop();
8.792 + }
8.793 + }
8.794 +
8.795 + /// <summary>
8.796 + /// Add a handler to detect removal of devices using WMI.
8.797 + /// </summary>
8.798 +
8.799 + private void AddDeviceRemovedHandler()
8.800 + {
8.801 + const Int32 pollingIntervalSeconds = 3;
8.802 + var scope = new ManagementScope("root\\CIMV2");
8.803 + scope.Options.EnablePrivileges = true;
8.804 +
8.805 + try
8.806 + {
8.807 + var q = new WqlEventQuery();
8.808 + q.EventClassName = "__InstanceDeletionEvent";
8.809 + q.WithinInterval = new TimeSpan(0, 0, pollingIntervalSeconds);
8.810 + q.Condition = @"TargetInstance ISA 'Win32_USBControllerdevice'";
8.811 + _deviceRemovedWatcher = new ManagementEventWatcher(scope, q);
8.812 + _deviceRemovedWatcher.EventArrived += DeviceRemoved;
8.813 + _deviceRemovedWatcher.Start();
8.814 + }
8.815 + catch (Exception e)
8.816 + {
8.817 + Debug.WriteLine(e.Message);
8.818 + if (_deviceRemovedWatcher != null)
8.819 + _deviceRemovedWatcher.Stop();
8.820 + }
8.821 + }
8.822 +
8.823 + /// <summary>
8.824 + /// Close the handle and FileStreams for a device.
8.825 + /// </summary>
8.826 + ///
8.827 + private void CloseCommunications()
8.828 + {
8.829 + if (_deviceData != null)
8.830 + {
8.831 + _deviceData.Close();
8.832 + }
8.833 +
8.834 + if ((_hidHandle != null) && (!(_hidHandle.IsInvalid)))
8.835 + {
8.836 + _hidHandle.Close();
8.837 + }
8.838 +
8.839 + // The next attempt to communicate will get a new handle and FileStreams.
8.840 +
8.841 + _deviceHandleObtained = false;
8.842 + }
8.843 +
8.844 + /// <summary>
8.845 + /// Search for a specific device.
8.846 + /// </summary>
8.847 +
8.848 + private void cmdFindDevice_Click(Object sender, EventArgs e)
8.849 + {
8.850 + try
8.851 + {
8.852 + if (_transferInProgress)
8.853 + {
8.854 + DisplayTransferInProgressMessage();
8.855 + }
8.856 + else
8.857 + {
8.858 + _deviceDetected = FindDeviceUsingWmi();
8.859 + if (_deviceDetected)
8.860 + {
8.861 + FindTheHid();
8.862 + }
8.863 + }
8.864 + }
8.865 + catch (Exception ex)
8.866 + {
8.867 + DisplayException(Name, ex);
8.868 + throw;
8.869 + }
8.870 + }
8.871 +
8.872 + /// <summary>
8.873 + /// Request to get a Feature report from the device.
8.874 + /// </summary>
8.875 + /// <param name="sender"></param>
8.876 + /// <param name="e"></param>
8.877 +
8.878 + private void cmdGetFeatureReport_Click(object sender, EventArgs e)
8.879 + {
8.880 + try
8.881 + {
8.882 + if (_transferInProgress)
8.883 + {
8.884 + DisplayTransferInProgressMessage();
8.885 + }
8.886 + else
8.887 + {
8.888 + // Don't allow another transfer request until this one completes.
8.889 + // Move the focus away from the button to prevent the focus from
8.890 + // switching to the next control in the tab order on disabling the button.
8.891 +
8.892 + fraControlTransfers.Focus();
8.893 + cmdGetFeatureReport.Enabled = false;
8.894 + _transferType = TransferTypes.Control;
8.895 + RequestToGetFeatureReport();
8.896 + }
8.897 + }
8.898 + catch (Exception ex)
8.899 + {
8.900 + DisplayException(Name, ex);
8.901 + throw;
8.902 + }
8.903 + }
8.904 +
8.905 + /// <summary>
8.906 + /// Request to get an Input report from the device using a control transfer.
8.907 + /// </summary>
8.908 + /// <param name="sender"></param>
8.909 + /// <param name="e"></param>
8.910 +
8.911 + private void cmdGetInputReportControl_Click(object sender, EventArgs e)
8.912 + {
8.913 + try
8.914 + {
8.915 + // Don't allow another transfer request until this one completes.
8.916 + // Move the focus away from the button to prevent the focus from
8.917 + // switching to the next control in the tab order on disabling the button.
8.918 +
8.919 + if (_transferInProgress)
8.920 + {
8.921 + DisplayTransferInProgressMessage();
8.922 + }
8.923 + else
8.924 + {
8.925 + fraControlTransfers.Focus();
8.926 + cmdGetInputReportControl.Enabled = false;
8.927 + _transferType = TransferTypes.Control;
8.928 + RequestToGetInputReport();
8.929 + }
8.930 + }
8.931 + catch (Exception ex)
8.932 + {
8.933 + DisplayException(Name, ex);
8.934 + throw;
8.935 + }
8.936 + }
8.937 +
8.938 + /// <summary>
8.939 + /// Request to get an Input report retrieved using interrupt transfers.
8.940 + /// </summary>
8.941 + /// <param name="sender"></param>
8.942 + /// <param name="e"></param>
8.943 + ///
8.944 + private void cmdGetInputReportInterrupt_Click(object sender, EventArgs e)
8.945 + {
8.946 + try
8.947 + {
8.948 + if (_transferInProgress)
8.949 + {
8.950 + DisplayTransferInProgressMessage();
8.951 + }
8.952 + else
8.953 + {
8.954 + // Don't allow another transfer request until this one completes.
8.955 + // Move the focus away from the button to prevent the focus from
8.956 + // switching to the next control in the tab order on disabling the button.
8.957 +
8.958 + fraInterruptTransfers.Focus();
8.959 + cmdGetInputReportInterrupt.Enabled = false;
8.960 + _transferType = TransferTypes.Interrupt;
8.961 + RequestToGetInputReport();
8.962 + }
8.963 + }
8.964 + catch (Exception ex)
8.965 + {
8.966 + DisplayException(Name, ex);
8.967 + throw;
8.968 + }
8.969 + }
8.970 +
8.971 + /// <summary>
8.972 + /// Set the number of Input reports the HID driver will store.
8.973 + /// </summary>
8.974 +
8.975 + private void cmdInputReportBufferSize_Click(Object sender, EventArgs e)
8.976 + {
8.977 + try
8.978 + {
8.979 + if (_transferInProgress)
8.980 + {
8.981 + DisplayTransferInProgressMessage();
8.982 + }
8.983 + else
8.984 + {
8.985 + SetInputReportBufferSize();
8.986 + }
8.987 + }
8.988 + catch
8.989 + (Exception ex)
8.990 + {
8.991 + DisplayException(Name, ex);
8.992 + throw;
8.993 + }
8.994 + }
8.995 +
8.996 + /// <summary>
8.997 + /// Alternate sending and getting a report.
8.998 + /// </summary>
8.999 + /// <param name="sender"></param>
8.1000 + /// <param name="e"></param>
8.1001 +
8.1002 + private void cmdPeriodicTransfers_Click(object sender, EventArgs e)
8.1003 + {
8.1004 + try
8.1005 + {
8.1006 + if (cmdPeriodicTransfers.Text == "Start")
8.1007 + {
8.1008 + if (_transferInProgress)
8.1009 + {
8.1010 + DisplayTransferInProgressMessage();
8.1011 + }
8.1012 + else
8.1013 + {
8.1014 + _sendOrGet = SendOrGet.Send;
8.1015 + PeriodicTransfersStart();
8.1016 + }
8.1017 + }
8.1018 + else
8.1019 + {
8.1020 + PeriodicTransfersStop();
8.1021 + }
8.1022 + }
8.1023 + catch (Exception ex)
8.1024 + {
8.1025 + DisplayException(Name, ex);
8.1026 + throw;
8.1027 + }
8.1028 + }
8.1029 +
8.1030 + /// <summary>
8.1031 + /// Request to send a Feature report using a control transfer.
8.1032 + /// </summary>
8.1033 + /// <param name="sender"></param>
8.1034 + /// <param name="e"></param>
8.1035 +
8.1036 + private void cmdSendFeatureReport_Click(object sender, EventArgs e)
8.1037 + {
8.1038 + try
8.1039 + {
8.1040 + if (_transferInProgress)
8.1041 + {
8.1042 + DisplayTransferInProgressMessage();
8.1043 + }
8.1044 + else
8.1045 + {
8.1046 + // Don't allow another transfer request until this one completes.
8.1047 + // Move the focus away from the button to prevent the focus from
8.1048 + // switching to the next control in the tab order on disabling the button.
8.1049 +
8.1050 + fraControlTransfers.Focus();
8.1051 + cmdSendFeatureReport.Enabled = false;
8.1052 + _transferType = TransferTypes.Control;
8.1053 + RequestToSendFeatureReport();
8.1054 + }
8.1055 + }
8.1056 + catch (Exception ex)
8.1057 + {
8.1058 + DisplayException(Name, ex);
8.1059 + throw;
8.1060 + }
8.1061 + }
8.1062 +
8.1063 + /// <summary>
8.1064 + /// Request to send an Output report using a control transfer.
8.1065 + /// </summary>
8.1066 + /// <param name="sender"></param>
8.1067 + /// <param name="e"></param>
8.1068 + ///
8.1069 + private void cmdSendOutputReportControl_Click(object sender, EventArgs e)
8.1070 + {
8.1071 + try
8.1072 + {
8.1073 + if (_transferInProgress)
8.1074 + {
8.1075 + DisplayTransferInProgressMessage();
8.1076 + }
8.1077 + else
8.1078 + {
8.1079 + // Don't allow another transfer request until this one completes.
8.1080 + // Move the focus away from the button to prevent the focus from
8.1081 + // switching to the next control in the tab order on disabling the button.
8.1082 +
8.1083 + fraControlTransfers.Focus();
8.1084 + cmdSendOutputReportControl.Enabled = false;
8.1085 + _transferType = TransferTypes.Control;
8.1086 + RequestToSendOutputReport();
8.1087 + }
8.1088 + }
8.1089 + catch (Exception ex)
8.1090 + {
8.1091 + DisplayException(Name, ex);
8.1092 + throw;
8.1093 + }
8.1094 + }
8.1095 +
8.1096 + /// <summary>
8.1097 + /// Request to send an Output report using an interrupt transfer.
8.1098 + /// </summary>
8.1099 + /// <param name="sender"></param>
8.1100 + /// <param name="e"></param>
8.1101 +
8.1102 + private void cmdSendOutputReportInterrupt_Click(object sender, EventArgs e)
8.1103 + {
8.1104 + try
8.1105 + {
8.1106 + if (_transferInProgress)
8.1107 + {
8.1108 + DisplayTransferInProgressMessage();
8.1109 + }
8.1110 + else
8.1111 + {
8.1112 + // Don't allow another transfer request until this one completes.
8.1113 + // Move the focus away from the button to prevent the focus from
8.1114 + // switching to the next control in the tab order on disabling the button.
8.1115 +
8.1116 + fraInterruptTransfers.Focus();
8.1117 + cmdSendOutputReportInterrupt.Enabled = false;
8.1118 + _transferType = TransferTypes.Interrupt;
8.1119 + RequestToSendOutputReport();
8.1120 + }
8.1121 + }
8.1122 + catch (Exception ex)
8.1123 + {
8.1124 + DisplayException(Name, ex);
8.1125 + throw;
8.1126 + }
8.1127 + }
8.1128 +
8.1129 + /// <summary>
8.1130 + /// Called on arrival of any device.
8.1131 + /// Calls a routine that searches to see if the desired device is present.
8.1132 + /// </summary>
8.1133 +
8.1134 + private void DeviceAdded(object sender, EventArrivedEventArgs e)
8.1135 + {
8.1136 + try
8.1137 + {
8.1138 + Debug.WriteLine("A USB device has been inserted");
8.1139 +
8.1140 + _deviceDetected = FindDeviceUsingWmi();
8.1141 + }
8.1142 + catch (Exception ex)
8.1143 + {
8.1144 + DisplayException(Name, ex);
8.1145 + throw;
8.1146 + }
8.1147 + }
8.1148 +
8.1149 + /// <summary>
8.1150 + /// Called if the user changes the Vendor ID or Product ID in the text box.
8.1151 + /// </summary>
8.1152 +
8.1153 + private void DeviceHasChanged()
8.1154 + {
8.1155 + try
8.1156 + {
8.1157 + // If a device was previously detected, stop receiving notifications about it.
8.1158 +
8.1159 + if (_deviceHandleObtained)
8.1160 + {
8.1161 + DeviceNotificationsStop();
8.1162 +
8.1163 + CloseCommunications();
8.1164 + }
8.1165 + // Look for a device that matches the Vendor ID and Product ID in the text boxes.
8.1166 +
8.1167 + FindTheHid();
8.1168 + }
8.1169 + catch (Exception ex)
8.1170 + {
8.1171 + DisplayException(Name, ex);
8.1172 + throw;
8.1173 + }
8.1174 + }
8.1175 +
8.1176 + /// <summary>
8.1177 + /// Add handlers to detect device arrival and removal.
8.1178 + /// </summary>
8.1179 +
8.1180 + private void DeviceNotificationsStart()
8.1181 + {
8.1182 + AddDeviceArrivedHandler();
8.1183 + AddDeviceRemovedHandler();
8.1184 + }
8.1185 +
8.1186 + /// <summary>
8.1187 + /// Stop receiving notifications about device arrival and removal
8.1188 + /// </summary>
8.1189 +
8.1190 + private void DeviceNotificationsStop()
8.1191 + {
8.1192 + try
8.1193 + {
8.1194 + if (_deviceArrivedWatcher != null)
8.1195 + _deviceArrivedWatcher.Stop();
8.1196 + if (_deviceRemovedWatcher != null)
8.1197 + _deviceRemovedWatcher.Stop();
8.1198 + }
8.1199 + catch (Exception ex)
8.1200 + {
8.1201 + DisplayException(Name, ex);
8.1202 + throw;
8.1203 + }
8.1204 + }
8.1205 +
8.1206 + /// <summary>
8.1207 + /// Called on removal of any device.
8.1208 + /// Calls a routine that searches to see if the desired device is still present.
8.1209 + /// </summary>
8.1210 + ///
8.1211 + private void DeviceRemoved(object sender, EventArgs e)
8.1212 + {
8.1213 + try
8.1214 + {
8.1215 + Debug.WriteLine("A USB device has been removed");
8.1216 +
8.1217 + _deviceDetected = FindDeviceUsingWmi();
8.1218 +
8.1219 + if (!_deviceDetected)
8.1220 + {
8.1221 + _deviceHandleObtained = false;
8.1222 + CloseCommunications();
8.1223 + }
8.1224 + }
8.1225 + catch (Exception ex)
8.1226 + {
8.1227 + DisplayException(Name, ex);
8.1228 + throw;
8.1229 + }
8.1230 + }
8.1231 +
8.1232 + /// <summary>
8.1233 + /// Displays received or written report data.
8.1234 + /// </summary>
8.1235 + ///
8.1236 + /// <param name="buffer"> contains the report data. </param>
8.1237 + /// <param name="currentReportType" > "Input", "Output", or "Feature"</param>
8.1238 + /// <param name="currentReadOrWritten" > "read" for Input and IN Feature reports, "written" for Output and OUT Feature reports.</param>
8.1239 +
8.1240 + private void DisplayReportData(Byte[] buffer, ReportTypes currentReportType, ReportReadOrWritten currentReadOrWritten)
8.1241 + {
8.1242 + try
8.1243 + {
8.1244 + Int32 count;
8.1245 +
8.1246 + LstResults.Items.Add(currentReportType.ToString() + " report has been " + currentReadOrWritten.ToString().ToLower() + ".");
8.1247 +
8.1248 + // Display the report data received in the form's list box.
8.1249 +
8.1250 + LstResults.Items.Add(" Report ID: " + String.Format("{0:X2} ", buffer[0]));
8.1251 + LstResults.Items.Add(" Report Data:");
8.1252 +
8.1253 + TxtBytesReceived.Text = "";
8.1254 +
8.1255 + for (count = 1; count <= buffer.Length - 1; count++)
8.1256 + {
8.1257 + // Display bytes as 2-character Hex strings.
8.1258 +
8.1259 + String byteValue = String.Format("{0:X2} ", buffer[count]);
8.1260 +
8.1261 + LstResults.Items.Add(" " + byteValue);
8.1262 +
8.1263 + // Display the received bytes in the text box.
8.1264 +
8.1265 + TxtBytesReceived.SelectionStart = TxtBytesReceived.Text.Length;
8.1266 + TxtBytesReceived.SelectedText = byteValue + Environment.NewLine;
8.1267 + }
8.1268 + ScrollToBottomOfListBox();
8.1269 + }
8.1270 + catch (Exception ex)
8.1271 + {
8.1272 + DisplayException(Name, ex);
8.1273 + throw;
8.1274 + }
8.1275 + }
8.1276 +
8.1277 + /// <summary>
8.1278 + /// Display a message if the user clicks a button when a transfer is in progress.
8.1279 + /// </summary>
8.1280 + ///
8.1281 + private void DisplayTransferInProgressMessage()
8.1282 + {
8.1283 + AccessForm(FormActions.AddItemToListBox, "Command not executed because a transfer is in progress.");
8.1284 + ScrollToBottomOfListBox();
8.1285 + }
8.1286 +
8.1287 + /// <summary>
8.1288 + /// Do periodic transfers.
8.1289 + /// </summary>
8.1290 + /// <param name="source"></param>
8.1291 + /// <param name="e"></param>
8.1292 + /// <remarks>
8.1293 + /// The timer is enabled only if continuous (periodic) transfers have been requested.
8.1294 + /// </remarks>
8.1295 +
8.1296 + private void DoPeriodicTransfers(object source, ElapsedEventArgs e)
8.1297 + {
8.1298 + try
8.1299 + {
8.1300 + PeriodicTransfers();
8.1301 + }
8.1302 + catch (Exception ex)
8.1303 + {
8.1304 + DisplayException(Name, ex);
8.1305 + throw;
8.1306 + }
8.1307 + }
8.1308 +
8.1309 + /// <summary>
8.1310 + /// Enable the command buttons on the form.
8.1311 + /// Needed after attempting a transfer and device not found.
8.1312 + /// </summary>
8.1313 + ///
8.1314 + private void EnableFormControls()
8.1315 + {
8.1316 + cmdGetInputReportInterrupt.Enabled = true;
8.1317 + cmdSendOutputReportControl.Enabled = true;
8.1318 + cmdGetInputReportControl.Enabled = true;
8.1319 + cmdGetFeatureReport.Enabled = true;
8.1320 + cmdSendFeatureReport.Enabled = true;
8.1321 + cmdPeriodicTransfers.Enabled = true;
8.1322 + cmdSendOutputReportInterrupt.Enabled = true;
8.1323 + }
8.1324 +
8.1325 + /// <summary>
8.1326 + /// Use the System.Management class to find a device by Vendor ID and Product ID using WMI. If found, display device properties.
8.1327 + /// </summary>
8.1328 + /// <remarks>
8.1329 + /// During debugging, if you stop the firmware but leave the device attached, the device may still be detected as present
8.1330 + /// but will be unable to communicate. The device will show up in Windows Device Manager as well.
8.1331 + /// This situation is unlikely to occur with a final product.
8.1332 + /// </remarks>
8.1333 +
8.1334 + private Boolean FindDeviceUsingWmi()
8.1335 + {
8.1336 + try
8.1337 + {
8.1338 + // Prepend "@" to string below to treat backslash as a normal character (not escape character):
8.1339 +
8.1340 + String deviceIdString = @"USB\VID_" + _myVendorId.ToString("X4") + "&PID_" + _myProductId.ToString("X4");
8.1341 +
8.1342 + _deviceDetected = false;
8.1343 + var searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PnPEntity");
8.1344 +
8.1345 + foreach (ManagementObject queryObj in searcher.Get())
8.1346 + {
8.1347 + if (queryObj["PNPDeviceID"].ToString().Contains(deviceIdString))
8.1348 + {
8.1349 + _deviceDetected = true;
8.1350 + MyMarshalDataToForm(FormActions.AddItemToListBox, "--------");
8.1351 + MyMarshalDataToForm(FormActions.AddItemToListBox, "My device found (WMI):");
8.1352 +
8.1353 + // Display device properties.
8.1354 +
8.1355 + foreach (WmiDeviceProperties wmiDeviceProperty in Enum.GetValues(typeof(WmiDeviceProperties)))
8.1356 + {
8.1357 + MyMarshalDataToForm(FormActions.AddItemToListBox, (wmiDeviceProperty.ToString() + ": " + queryObj[wmiDeviceProperty.ToString()]));
8.1358 + Debug.WriteLine(wmiDeviceProperty.ToString() + ": {0}", queryObj[wmiDeviceProperty.ToString()]);
8.1359 + }
8.1360 + MyMarshalDataToForm(FormActions.AddItemToListBox, "--------");
8.1361 + MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
8.1362 + }
8.1363 + }
8.1364 + if (!_deviceDetected)
8.1365 + {
8.1366 + MyMarshalDataToForm(FormActions.AddItemToListBox, "My device not found (WMI)");
8.1367 + MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
8.1368 + }
8.1369 + return _deviceDetected;
8.1370 + }
8.1371 + catch (Exception ex)
8.1372 + {
8.1373 + DisplayException(Name, ex);
8.1374 + throw;
8.1375 + }
8.1376 + }
8.1377 +
8.1378 + /// <summary>
8.1379 + /// Call HID functions that use Win32 API functions to locate a HID-class device
8.1380 + /// by its Vendor ID and Product ID. Open a handle to the device.
8.1381 + /// </summary>
8.1382 + ///
8.1383 + /// <returns>
8.1384 + /// True if the device is detected, False if not detected.
8.1385 + /// </returns>
8.1386 +
8.1387 + private Boolean FindTheHid()
8.1388 + {
8.1389 + var devicePathName = new String[128];
8.1390 + String myDevicePathName = "";
8.1391 +
8.1392 + try
8.1393 + {
8.1394 + _deviceHandleObtained = false;
8.1395 + CloseCommunications();
8.1396 +
8.1397 + // Get the device's Vendor ID and Product ID from the form's text boxes.
8.1398 +
8.1399 + GetVendorAndProductIDsFromTextBoxes(ref _myVendorId, ref _myProductId);
8.1400 +
8.1401 + // Get the HID-class GUID.
8.1402 +
8.1403 + Guid hidGuid = _myHid.GetHidGuid();
8.1404 +
8.1405 + String functionName = "GetHidGuid";
8.1406 + Debug.WriteLine(_myDebugging.ResultOfApiCall(functionName));
8.1407 + Debug.WriteLine(" GUID for system HIDs: " + hidGuid.ToString());
8.1408 +
8.1409 + // Fill an array with the device path names of all attached HIDs.
8.1410 +
8.1411 + Boolean availableHids = _myDeviceManagement.FindDeviceFromGuid(hidGuid, ref devicePathName);
8.1412 +
8.1413 + // If there is at least one HID, attempt to read the Vendor ID and Product ID
8.1414 + // of each device until there is a match or all devices have been examined.
8.1415 +
8.1416 + if (availableHids)
8.1417 + {
8.1418 + Int32 memberIndex = 0;
8.1419 +
8.1420 + do
8.1421 + {
8.1422 + // Open the handle without read/write access to enable getting information about any HID, even system keyboards and mice.
8.1423 +
8.1424 + _hidHandle = _myHid.OpenHandle(devicePathName[memberIndex], false);
8.1425 +
8.1426 + functionName = "CreateFile";
8.1427 + Debug.WriteLine(_myDebugging.ResultOfApiCall(functionName));
8.1428 + Debug.WriteLine(" Returned handle: " + _hidHandle);
8.1429 +
8.1430 + if (!_hidHandle.IsInvalid)
8.1431 + {
8.1432 + // The returned handle is valid,
8.1433 + // so find out if this is the device we're looking for.
8.1434 +
8.1435 + _myHid.DeviceAttributes.Size = Marshal.SizeOf(_myHid.DeviceAttributes);
8.1436 +
8.1437 + Boolean success = _myHid.GetAttributes(_hidHandle, ref _myHid.DeviceAttributes);
8.1438 +
8.1439 + if (success)
8.1440 + {
8.1441 + Debug.WriteLine(" HIDD_ATTRIBUTES structure filled without error.");
8.1442 + Debug.WriteLine(" Structure size: " + _myHid.DeviceAttributes.Size);
8.1443 + Debug.WriteLine(" Vendor ID: " + Convert.ToString(_myHid.DeviceAttributes.VendorID, 16));
8.1444 + Debug.WriteLine(" Product ID: " + Convert.ToString(_myHid.DeviceAttributes.ProductID, 16));
8.1445 + Debug.WriteLine(" Version Number: " + Convert.ToString(_myHid.DeviceAttributes.VersionNumber, 16));
8.1446 +
8.1447 + if ((_myHid.DeviceAttributes.VendorID == _myVendorId) && (_myHid.DeviceAttributes.ProductID == _myProductId))
8.1448 + {
8.1449 + Debug.WriteLine(" Handle obtained to my device");
8.1450 +
8.1451 + // Display the information in form's list box.
8.1452 +
8.1453 + MyMarshalDataToForm(FormActions.AddItemToListBox, "Handle obtained to my device:");
8.1454 + MyMarshalDataToForm(FormActions.AddItemToListBox, " Vendor ID= " + Convert.ToString(_myHid.DeviceAttributes.VendorID, 16));
8.1455 + MyMarshalDataToForm(FormActions.AddItemToListBox, " Product ID = " + Convert.ToString(_myHid.DeviceAttributes.ProductID, 16));
8.1456 + MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
8.1457 +
8.1458 + _deviceHandleObtained = true;
8.1459 +
8.1460 + myDevicePathName = devicePathName[memberIndex];
8.1461 + }
8.1462 + else
8.1463 + {
8.1464 + // It's not a match, so close the handle.
8.1465 +
8.1466 + _deviceHandleObtained = false;
8.1467 + _hidHandle.Close();
8.1468 + }
8.1469 + }
8.1470 + else
8.1471 + {
8.1472 + // There was a problem retrieving the information.
8.1473 +
8.1474 + Debug.WriteLine(" Error in filling HIDD_ATTRIBUTES structure.");
8.1475 + _deviceHandleObtained = false;
8.1476 + _hidHandle.Close();
8.1477 + }
8.1478 + }
8.1479 +
8.1480 + // Keep looking until we find the device or there are no devices left to examine.
8.1481 +
8.1482 + memberIndex = memberIndex + 1;
8.1483 + }
8.1484 + while (!((_deviceHandleObtained || (memberIndex == devicePathName.Length))));
8.1485 + }
8.1486 +
8.1487 + if (_deviceHandleObtained)
8.1488 + {
8.1489 + // The device was detected.
8.1490 + // Learn the capabilities of the device.
8.1491 +
8.1492 + _myHid.Capabilities = _myHid.GetDeviceCapabilities(_hidHandle);
8.1493 +
8.1494 + // Find out if the device is a system mouse or keyboard.
8.1495 +
8.1496 + _hidUsage = _myHid.GetHidUsage(_myHid.Capabilities);
8.1497 +
8.1498 + // Get the Input report buffer size.
8.1499 +
8.1500 + GetInputReportBufferSize();
8.1501 + MyMarshalDataToForm(FormActions.EnableInputReportBufferSize, "");
8.1502 +
8.1503 + //Close the handle and reopen it with read/write access.
8.1504 +
8.1505 + _hidHandle.Close();
8.1506 +
8.1507 + _hidHandle = _myHid.OpenHandle(myDevicePathName, true);
8.1508 +
8.1509 + if (_hidHandle.IsInvalid)
8.1510 + {
8.1511 + MyMarshalDataToForm(FormActions.AddItemToListBox, "The device is a system " + _hidUsage + ".");
8.1512 + MyMarshalDataToForm(FormActions.AddItemToListBox, "Windows 2000 and later obtain exclusive access to Input and Output reports for this devices.");
8.1513 + MyMarshalDataToForm(FormActions.AddItemToListBox, "Windows 8 also obtains exclusive access to Feature reports.");
8.1514 + MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
8.1515 + }
8.1516 + else
8.1517 + {
8.1518 + if (_myHid.Capabilities.InputReportByteLength > 0)
8.1519 + {
8.1520 + // Set the size of the Input report buffer.
8.1521 +
8.1522 + var inputReportBuffer = new Byte[_myHid.Capabilities.InputReportByteLength];
8.1523 +
8.1524 + _deviceData = new FileStream(_hidHandle, FileAccess.Read | FileAccess.Write, inputReportBuffer.Length, false);
8.1525 + }
8.1526 +
8.1527 + if (_myHid.Capabilities.OutputReportByteLength > 0)
8.1528 + {
8.1529 + Byte[] outputReportBuffer = null;
8.1530 + }
8.1531 + // Flush any waiting reports in the input buffer. (optional)
8.1532 +
8.1533 + _myHid.FlushQueue(_hidHandle);
8.1534 + }
8.1535 + }
8.1536 + else
8.1537 + {
8.1538 + MyMarshalDataToForm(FormActions.AddItemToListBox, "Device not found.");
8.1539 + MyMarshalDataToForm(FormActions.DisableInputReportBufferSize, "");
8.1540 + EnableFormControls();
8.1541 + MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
8.1542 + }
8.1543 + return _deviceHandleObtained;
8.1544 + }
8.1545 + catch (Exception ex)
8.1546 + {
8.1547 + DisplayException(Name, ex);
8.1548 + throw;
8.1549 + }
8.1550 + }
8.1551 +
8.1552 + /// <summary>
8.1553 + /// Perform shutdown operations.
8.1554 + /// </summary>
8.1555 +
8.1556 + private void frmMain_Closed(Object eventSender, EventArgs eventArgs)
8.1557 + {
8.1558 + try
8.1559 + {
8.1560 + Shutdown();
8.1561 + }
8.1562 + catch (Exception ex)
8.1563 + {
8.1564 + DisplayException(Name, ex);
8.1565 + throw;
8.1566 + }
8.1567 + }
8.1568 +
8.1569 + /// <summary>
8.1570 + /// Perform startup operations.
8.1571 + /// </summary>
8.1572 +
8.1573 + private void frmMain_Load(Object eventSender, EventArgs eventArgs)
8.1574 + {
8.1575 + try
8.1576 + {
8.1577 + FrmMy = this;
8.1578 + Startup();
8.1579 + }
8.1580 + catch (Exception ex)
8.1581 + {
8.1582 + DisplayException(Name, ex);
8.1583 + throw;
8.1584 + }
8.1585 + }
8.1586 +
8.1587 + private void GetBytesToSend()
8.1588 + {
8.1589 + try
8.1590 + {
8.1591 + // Get the bytes to send in a report from the combo boxes.
8.1592 + // Increment the values if the autoincrement check box is selected.
8.1593 +
8.1594 + if (ChkAutoincrement.Checked)
8.1595 + {
8.1596 + if (CboByte0.SelectedIndex < 255)
8.1597 + {
8.1598 + CboByte0.SelectedIndex = CboByte0.SelectedIndex + 1;
8.1599 + }
8.1600 + else
8.1601 + {
8.1602 + CboByte0.SelectedIndex = 0;
8.1603 + }
8.1604 + if (CboByte1.SelectedIndex < 255)
8.1605 + {
8.1606 + CboByte1.SelectedIndex = CboByte1.SelectedIndex + 1;
8.1607 + }
8.1608 + else
8.1609 + {
8.1610 + CboByte1.SelectedIndex = 0;
8.1611 + }
8.1612 + }
8.1613 + }
8.1614 + catch (Exception ex)
8.1615 + {
8.1616 + DisplayException(Name, ex);
8.1617 + throw;
8.1618 + }
8.1619 + }
8.1620 +
8.1621 + /// <summary>
8.1622 + /// Find and display the number of Input buffers
8.1623 + /// (the number of Input reports the HID driver will store).
8.1624 + /// </summary>
8.1625 +
8.1626 + private void GetInputReportBufferSize()
8.1627 + {
8.1628 + Int32 numberOfInputBuffers = 0;
8.1629 + Boolean success;
8.1630 +
8.1631 + try
8.1632 + {
8.1633 + // Get the number of input buffers.
8.1634 +
8.1635 + _myHid.GetNumberOfInputBuffers(_hidHandle, ref numberOfInputBuffers);
8.1636 +
8.1637 + // Display the result in the text box.
8.1638 +
8.1639 + MyMarshalDataToForm(FormActions.SetInputReportBufferSize, Convert.ToString(numberOfInputBuffers));
8.1640 + }
8.1641 + catch (Exception ex)
8.1642 + {
8.1643 + DisplayException(Name, ex);
8.1644 + throw;
8.1645 + }
8.1646 + }
8.1647 +
8.1648 + /// <summary>
8.1649 + /// Retrieve a Vendor ID and Product ID in hexadecimal
8.1650 + /// from the form's text boxes and convert the text to Int32s.
8.1651 + /// </summary>
8.1652 + ///
8.1653 + /// <param name="myVendorId"> the Vendor ID</param>
8.1654 + /// <param name="myProductId"> the Product ID</param>
8.1655 +
8.1656 + private void GetVendorAndProductIDsFromTextBoxes(ref Int32 myVendorId, ref Int32 myProductId)
8.1657 + {
8.1658 + try
8.1659 + {
8.1660 + myVendorId = Int32.Parse(txtVendorID.Text, NumberStyles.AllowHexSpecifier);
8.1661 + myProductId = Int32.Parse(txtProductID.Text, NumberStyles.AllowHexSpecifier);
8.1662 + }
8.1663 + catch (Exception ex)
8.1664 + {
8.1665 + DisplayException(Name, ex);
8.1666 + throw;
8.1667 + }
8.1668 + }
8.1669 +
8.1670 + /// <summary>
8.1671 + /// Initialize the elements on the form.
8.1672 + /// </summary>
8.1673 +
8.1674 + private void InitializeDisplay()
8.1675 + {
8.1676 + try
8.1677 + {
8.1678 + // Create a dropdown list box for each byte to send in a report.
8.1679 + // Display the values as 2-character hex strings.
8.1680 +
8.1681 + Int16 count;
8.1682 + for (count = 0; count <= 255; count++)
8.1683 + {
8.1684 + String byteValue = String.Format("{0:X2} ", count);
8.1685 + FrmMy.CboByte0.Items.Insert(count, byteValue);
8.1686 + FrmMy.CboByte1.Items.Insert(count, byteValue);
8.1687 + }
8.1688 +
8.1689 + // Select a default value for each box
8.1690 +
8.1691 + FrmMy.CboByte0.SelectedIndex = 0;
8.1692 + FrmMy.CboByte1.SelectedIndex = 128;
8.1693 + FrmMy.radInputOutputInterrupt.Checked = true;
8.1694 +
8.1695 + // Check the autoincrement box to increment the values each time a report is sent.
8.1696 +
8.1697 + ChkAutoincrement.CheckState = CheckState.Checked;
8.1698 +
8.1699 + // Don't allow the user to select an input report buffer size until there is
8.1700 + // a handle to a HID.
8.1701 +
8.1702 + cmdInputReportBufferSize.Focus();
8.1703 + cmdInputReportBufferSize.Enabled = false;
8.1704 +
8.1705 + LstResults.Items.Add("For a more detailed event log, view debug statements in Visual Studio's Output window:");
8.1706 + LstResults.Items.Add("Click Build > Configuration Manager > Active Solution Configuration > Debug > Close.");
8.1707 + LstResults.Items.Add("Then click View > Output.");
8.1708 + LstResults.Items.Add("");
8.1709 + }
8.1710 + catch (Exception ex)
8.1711 + {
8.1712 + DisplayException(Name, ex);
8.1713 + throw;
8.1714 + }
8.1715 + }
8.1716 +
8.1717 + /// <summary>
8.1718 + /// Enables accessing a form's controls from another thread
8.1719 + /// </summary>
8.1720 + ///
8.1721 + /// <param name="action"> a FormActions member that names the action to perform on the form </param>
8.1722 + /// <param name="textToDisplay"> text that the form displays or the code uses for
8.1723 + /// another purpose. Actions that don't use text ignore this parameter. </param>
8.1724 +
8.1725 + private void MyMarshalDataToForm(FormActions action, String textToDisplay)
8.1726 + {
8.1727 + try
8.1728 + {
8.1729 + object[] args = { action, textToDisplay };
8.1730 +
8.1731 + // The AccessForm routine contains the code that accesses the form.
8.1732 +
8.1733 + MarshalDataToForm marshalDataToFormDelegate = AccessForm;
8.1734 +
8.1735 + // Execute AccessForm, passing the parameters in args.
8.1736 +
8.1737 + Invoke(marshalDataToFormDelegate, args);
8.1738 + }
8.1739 + catch (Exception ex)
8.1740 + {
8.1741 + DisplayException(Name, ex);
8.1742 + throw;
8.1743 + }
8.1744 + }
8.1745 +
8.1746 + /// <summary>
8.1747 + /// Timeout if read via interrupt transfer doesn't return.
8.1748 + /// </summary>
8.1749 +
8.1750 + private void OnReadTimeout()
8.1751 + {
8.1752 + try
8.1753 + {
8.1754 + MyMarshalDataToForm(FormActions.AddItemToListBox, "The attempt to read a report timed out.");
8.1755 + MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
8.1756 + CloseCommunications();
8.1757 + MyMarshalDataToForm(FormActions.EnableGetInputReportInterruptTransfer, "");
8.1758 + _transferInProgress = false;
8.1759 + _sendOrGet = SendOrGet.Send;
8.1760 + }
8.1761 + catch (Exception ex)
8.1762 + {
8.1763 + DisplayException(Name, ex);
8.1764 + throw;
8.1765 + }
8.1766 + }
8.1767 +
8.1768 + /// <summary>
8.1769 + /// Timeout if write via interrupt transfer doesn't return.
8.1770 + /// </summary>
8.1771 +
8.1772 + private void OnWriteTimeout()
8.1773 + {
8.1774 + try
8.1775 + {
8.1776 + MyMarshalDataToForm(FormActions.AddItemToListBox, "The attempt to write a report timed out.");
8.1777 + MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
8.1778 + CloseCommunications();
8.1779 + MyMarshalDataToForm(FormActions.EnableSendOutputReportInterrupt, "");
8.1780 + _transferInProgress = false;
8.1781 + _sendOrGet = SendOrGet.Get;
8.1782 + }
8.1783 + catch (Exception ex)
8.1784 + {
8.1785 + DisplayException(Name, ex);
8.1786 + throw;
8.1787 + }
8.1788 + }
8.1789 +
8.1790 + /// <summary>
8.1791 + /// Alternat sending and getting a report.
8.1792 + /// </summary>
8.1793 +
8.1794 + private void PeriodicTransfers()
8.1795 + {
8.1796 + try
8.1797 + {
8.1798 + if (!_transferInProgress)
8.1799 + {
8.1800 + if (_reportType == ReportTypes.Feature)
8.1801 + {
8.1802 + SendOrGetFeatureReport();
8.1803 + }
8.1804 + else
8.1805 + {
8.1806 + // Output and Input reports
8.1807 +
8.1808 + SendOutputReportOrGetInputReport();
8.1809 + }
8.1810 + }
8.1811 + }
8.1812 + catch (Exception ex)
8.1813 + {
8.1814 + DisplayException(Name, ex);
8.1815 + throw;
8.1816 + }
8.1817 + }
8.1818 +
8.1819 + /// <summary>
8.1820 + /// Start doing periodic transfers.
8.1821 + /// </summary>
8.1822 +
8.1823 + private void PeriodicTransfersStart()
8.1824 + {
8.1825 + // Don't allow changing the transfer type while transfers are in progress.
8.1826 +
8.1827 + if (radFeature.Checked)
8.1828 + {
8.1829 + radInputOutputControl.Enabled = false;
8.1830 + radInputOutputInterrupt.Enabled = false;
8.1831 + }
8.1832 + else if (radInputOutputControl.Checked)
8.1833 + {
8.1834 + radFeature.Enabled = false;
8.1835 + radInputOutputInterrupt.Enabled = false;
8.1836 + }
8.1837 + else if (radInputOutputInterrupt.Checked)
8.1838 + {
8.1839 + radFeature.Enabled = false;
8.1840 + radInputOutputControl.Enabled = false;
8.1841 + }
8.1842 +
8.1843 + // Change the command button's text.
8.1844 +
8.1845 + cmdPeriodicTransfers.Text = "Stop";
8.1846 +
8.1847 + // Enable the timer event to trigger a set of transfers.
8.1848 +
8.1849 + _periodicTransfers.Start();
8.1850 +
8.1851 + cmdPeriodicTransfers.Enabled = true;
8.1852 +
8.1853 + if (radInputOutputInterrupt.Checked)
8.1854 + {
8.1855 + _transferType = TransferTypes.Interrupt;
8.1856 + _reportType = ReportTypes.Output;
8.1857 + }
8.1858 + else if (radInputOutputControl.Checked)
8.1859 + {
8.1860 + _transferType = TransferTypes.Control;
8.1861 + _reportType = ReportTypes.Output;
8.1862 + }
8.1863 + else if (radFeature.Checked)
8.1864 + {
8.1865 + _transferType = TransferTypes.Control;
8.1866 + _reportType = ReportTypes.Feature;
8.1867 + }
8.1868 + _periodicTransfersRequested = true;
8.1869 + PeriodicTransfers();
8.1870 + }
8.1871 +
8.1872 + /// <summary>
8.1873 + /// Stop doing periodic transfers.
8.1874 + /// </summary>
8.1875 +
8.1876 + private void PeriodicTransfersStop()
8.1877 + {
8.1878 + // Stop doing continuous transfers.
8.1879 +
8.1880 + _periodicTransfersRequested = false;
8.1881 +
8.1882 + // Disable the timer that triggers the transfers.
8.1883 +
8.1884 + _periodicTransfers.Stop();
8.1885 + cmdPeriodicTransfers.Enabled = true;
8.1886 +
8.1887 + // Change the command button's text.
8.1888 +
8.1889 + cmdPeriodicTransfers.Text = "Start";
8.1890 +
8.1891 + // Re-allow changing the transfer type.
8.1892 +
8.1893 + radFeature.Enabled = true;
8.1894 + radInputOutputControl.Enabled = true;
8.1895 + radInputOutputInterrupt.Enabled = true;
8.1896 + }
8.1897 +
8.1898 + private void radInputOutputControl_CheckedChanged(object sender, EventArgs e)
8.1899 + {
8.1900 + }
8.1901 +
8.1902 + private void radInputOutputInterrupt_CheckedChanged(object sender, EventArgs e)
8.1903 + {
8.1904 + }
8.1905 +
8.1906 + private void radFeature_CheckedChanged(object sender, EventArgs e)
8.1907 + {
8.1908 + }
8.1909 +
8.1910 + /// <summary>
8.1911 + /// Request a Feature report.
8.1912 + /// Assumes report ID = 0.
8.1913 + /// </summary>
8.1914 +
8.1915 + private void RequestToGetFeatureReport()
8.1916 + {
8.1917 + String byteValue = null;
8.1918 +
8.1919 + try
8.1920 + {
8.1921 + // If the device hasn't been detected, was removed, or timed out on a previous attempt
8.1922 + // to access it, look for the device.
8.1923 +
8.1924 + if (!_deviceHandleObtained)
8.1925 + {
8.1926 + _deviceHandleObtained = FindTheHid();
8.1927 + }
8.1928 +
8.1929 + if (_deviceHandleObtained)
8.1930 + {
8.1931 + Byte[] inFeatureReportBuffer = null;
8.1932 +
8.1933 + if ((_myHid.Capabilities.FeatureReportByteLength > 0))
8.1934 + {
8.1935 + // The HID has a Feature report.
8.1936 + // Read a report from the device.
8.1937 +
8.1938 + // Set the size of the Feature report buffer.
8.1939 +
8.1940 + if ((_myHid.Capabilities.FeatureReportByteLength > 0))
8.1941 + {
8.1942 + inFeatureReportBuffer = new Byte[_myHid.Capabilities.FeatureReportByteLength];
8.1943 + }
8.1944 +
8.1945 + // Read a report.
8.1946 +
8.1947 + Boolean success = _myHid.GetFeatureReport(_hidHandle, ref inFeatureReportBuffer);
8.1948 +
8.1949 + if (success)
8.1950 + {
8.1951 + DisplayReportData(inFeatureReportBuffer, ReportTypes.Feature, ReportReadOrWritten.Read);
8.1952 + }
8.1953 + else
8.1954 + {
8.1955 + CloseCommunications();
8.1956 + MyMarshalDataToForm(FormActions.AddItemToListBox, "The attempt to read a Feature report failed.");
8.1957 + ScrollToBottomOfListBox();
8.1958 + }
8.1959 + }
8.1960 + else
8.1961 + {
8.1962 + MyMarshalDataToForm(FormActions.AddItemToListBox, "The HID doesn't have a Feature report.");
8.1963 + ScrollToBottomOfListBox();
8.1964 + }
8.1965 + }
8.1966 + _transferInProgress = false;
8.1967 + cmdGetFeatureReport.Enabled = true;
8.1968 + }
8.1969 + catch (Exception ex)
8.1970 + {
8.1971 + DisplayException(Name, ex);
8.1972 + throw;
8.1973 + }
8.1974 + }
8.1975 +
8.1976 + /// <summary>
8.1977 + /// Request an Input report.
8.1978 + /// Assumes report ID = 0.
8.1979 + /// </summary>
8.1980 +
8.1981 + private async void RequestToGetInputReport()
8.1982 + {
8.1983 + const Int32 readTimeout = 5000;
8.1984 +
8.1985 + String byteValue = null;
8.1986 + Byte[] inputReportBuffer = null;
8.1987 +
8.1988 + try
8.1989 + {
8.1990 + Boolean success = false;
8.1991 +
8.1992 + // If the device hasn't been detected, was removed, or timed out on a previous attempt
8.1993 + // to access it, look for the device.
8.1994 +
8.1995 + if (!_deviceHandleObtained)
8.1996 + {
8.1997 + _deviceHandleObtained = FindTheHid();
8.1998 + }
8.1999 +
8.2000 + if (_deviceHandleObtained)
8.2001 + {
8.2002 + // Don't attempt to exchange reports if valid handles aren't available
8.2003 + // (as for a mouse or keyboard under Windows 2000 and later.)
8.2004 +
8.2005 + if (!_hidHandle.IsInvalid)
8.2006 + {
8.2007 + // Read an Input report.
8.2008 +
8.2009 + // Don't attempt to send an Input report if the HID has no Input report.
8.2010 + // (The HID spec requires all HIDs to have an interrupt IN endpoint,
8.2011 + // which suggests that all HIDs must support Input reports.)
8.2012 +
8.2013 + if (_myHid.Capabilities.InputReportByteLength > 0)
8.2014 + {
8.2015 + // Set the size of the Input report buffer.
8.2016 +
8.2017 + inputReportBuffer = new Byte[_myHid.Capabilities.InputReportByteLength];
8.2018 +
8.2019 + if (_transferType.Equals(TransferTypes.Control))
8.2020 + {
8.2021 + {
8.2022 + _transferInProgress = true;
8.2023 +
8.2024 + // Read a report using a control transfer.
8.2025 +
8.2026 + success = _myHid.GetInputReportViaControlTransfer(_hidHandle, ref inputReportBuffer);
8.2027 + cmdGetInputReportControl.Enabled = true;
8.2028 + _transferInProgress = false;
8.2029 + }
8.2030 + }
8.2031 + else
8.2032 + {
8.2033 + {
8.2034 + _transferInProgress = true;
8.2035 +
8.2036 + // Read a report using interrupt transfers.
8.2037 + // Timeout if no report available.
8.2038 + // To enable reading a report without blocking the calling thread, uses Filestream's ReadAsync method.
8.2039 +
8.2040 + // Create a delegate to execute on a timeout.
8.2041 +
8.2042 + Action onReadTimeoutAction = OnReadTimeout;
8.2043 +
8.2044 + // The CancellationTokenSource specifies the timeout value and the action to take on a timeout.
8.2045 +
8.2046 + var cts = new CancellationTokenSource();
8.2047 +
8.2048 + // Cancel the read if it hasn't completed after a timeout.
8.2049 +
8.2050 + cts.CancelAfter(readTimeout);
8.2051 +
8.2052 + // Specify the function to call on a timeout.
8.2053 +
8.2054 + cts.Token.Register(onReadTimeoutAction);
8.2055 +
8.2056 + // Stops waiting when data is available or on timeout:
8.2057 +
8.2058 + Int32 bytesRead = await _myHid.GetInputReportViaInterruptTransfer(_deviceData, inputReportBuffer, cts);
8.2059 +
8.2060 + // Arrive here only if the operation completed.
8.2061 +
8.2062 + // Dispose to stop the timeout timer.
8.2063 +
8.2064 + cts.Dispose();
8.2065 +
8.2066 + _transferInProgress = false;
8.2067 + cmdGetInputReportInterrupt.Enabled = true;
8.2068 +
8.2069 + if (bytesRead > 0)
8.2070 + {
8.2071 + success = true;
8.2072 + Debug.Print("bytes read (includes report ID) = " + Convert.ToString(bytesRead));
8.2073 + }
8.2074 + }
8.2075 + }
8.2076 + }
8.2077 + else
8.2078 + {
8.2079 + MyMarshalDataToForm(FormActions.AddItemToListBox, "No attempt to read an Input report was made.");
8.2080 + MyMarshalDataToForm(FormActions.AddItemToListBox, "The HID doesn't have an Input report.");
8.2081 + }
8.2082 + }
8.2083 + else
8.2084 + {
8.2085 + MyMarshalDataToForm(FormActions.AddItemToListBox, "Invalid handle.");
8.2086 + MyMarshalDataToForm(FormActions.AddItemToListBox,
8.2087 + "No attempt to write an Output report or read an Input report was made.");
8.2088 + }
8.2089 +
8.2090 + if (success)
8.2091 + {
8.2092 + DisplayReportData(inputReportBuffer, ReportTypes.Input, ReportReadOrWritten.Read);
8.2093 + }
8.2094 + else
8.2095 + {
8.2096 + CloseCommunications();
8.2097 + MyMarshalDataToForm(FormActions.AddItemToListBox, "The attempt to read an Input report has failed.");
8.2098 + ScrollToBottomOfListBox();
8.2099 + }
8.2100 + }
8.2101 + }
8.2102 +
8.2103 + catch (Exception ex)
8.2104 + {
8.2105 + DisplayException(Name, ex);
8.2106 + throw;
8.2107 + }
8.2108 + }
8.2109 +
8.2110 + /// <summary>
8.2111 + /// Sends a Feature report.
8.2112 + /// Assumes report ID = 0.
8.2113 + /// </summary>
8.2114 +
8.2115 + private void RequestToSendFeatureReport()
8.2116 + {
8.2117 + String byteValue = null;
8.2118 +
8.2119 + try
8.2120 + {
8.2121 + _transferInProgress = true;
8.2122 +
8.2123 + // If the device hasn't been detected, was removed, or timed out on a previous attempt
8.2124 + // to access it, look for the device.
8.2125 +
8.2126 + if (!_deviceHandleObtained)
8.2127 + {
8.2128 + _deviceHandleObtained = FindTheHid();
8.2129 + }
8.2130 +
8.2131 + if (_deviceHandleObtained)
8.2132 + {
8.2133 + GetBytesToSend();
8.2134 +
8.2135 + if ((_myHid.Capabilities.FeatureReportByteLength > 0))
8.2136 + {
8.2137 + // The HID has a Feature report.
8.2138 + // Set the size of the Feature report buffer.
8.2139 +
8.2140 + var outFeatureReportBuffer = new Byte[_myHid.Capabilities.FeatureReportByteLength];
8.2141 +
8.2142 + // Store the report ID in the buffer.
8.2143 +
8.2144 + outFeatureReportBuffer[0] = 0;
8.2145 +
8.2146 + // Store the report data following the report ID.
8.2147 + // Use the data in the combo boxes on the form.
8.2148 +
8.2149 + outFeatureReportBuffer[1] = Convert.ToByte(CboByte0.SelectedIndex);
8.2150 +
8.2151 + if (outFeatureReportBuffer.GetUpperBound(0) > 1)
8.2152 + {
8.2153 + outFeatureReportBuffer[2] = Convert.ToByte(CboByte1.SelectedIndex);
8.2154 + }
8.2155 +
8.2156 + // Write a report to the device
8.2157 +
8.2158 + Boolean success = _myHid.SendFeatureReport(_hidHandle, outFeatureReportBuffer);
8.2159 +
8.2160 + if (success)
8.2161 + {
8.2162 + DisplayReportData(outFeatureReportBuffer, ReportTypes.Feature, ReportReadOrWritten.Written);
8.2163 + }
8.2164 + else
8.2165 + {
8.2166 + CloseCommunications();
8.2167 + AccessForm(FormActions.AddItemToListBox, "The attempt to send a Feature report failed.");
8.2168 + ScrollToBottomOfListBox();
8.2169 + }
8.2170 + }
8.2171 +
8.2172 + else
8.2173 + {
8.2174 + AccessForm(FormActions.AddItemToListBox, "The HID doesn't have a Feature report.");
8.2175 + ScrollToBottomOfListBox();
8.2176 + }
8.2177 +
8.2178 + }
8.2179 + _transferInProgress = false;
8.2180 + cmdSendFeatureReport.Enabled = true;
8.2181 + ScrollToBottomOfListBox();
8.2182 +
8.2183 + }
8.2184 + catch (Exception ex)
8.2185 + {
8.2186 + DisplayException(Name, ex);
8.2187 + throw;
8.2188 + }
8.2189 + }
8.2190 +
8.2191 + /// <summary>
8.2192 + /// Sends an Output report.
8.2193 + /// Assumes report ID = 0.
8.2194 + /// </summary>
8.2195 +
8.2196 + private async void RequestToSendOutputReport()
8.2197 + {
8.2198 + const Int32 writeTimeout = 5000;
8.2199 + String byteValue = null;
8.2200 +
8.2201 + try
8.2202 + {
8.2203 + // If the device hasn't been detected, was removed, or timed out on a previous attempt
8.2204 + // to access it, look for the device.
8.2205 +
8.2206 + if (!_deviceHandleObtained)
8.2207 + {
8.2208 + _deviceHandleObtained = FindTheHid();
8.2209 + }
8.2210 +
8.2211 + if (_deviceHandleObtained)
8.2212 + {
8.2213 + GetBytesToSend();
8.2214 + }
8.2215 + // Don't attempt to exchange reports if valid handles aren't available
8.2216 + // (as for a mouse or keyboard.)
8.2217 +
8.2218 + if (!_hidHandle.IsInvalid)
8.2219 + {
8.2220 + // Don't attempt to send an Output report if the HID has no Output report.
8.2221 +
8.2222 + if (_myHid.Capabilities.OutputReportByteLength > 0)
8.2223 + {
8.2224 + // Set the size of the Output report buffer.
8.2225 +
8.2226 + var outputReportBuffer = new Byte[_myHid.Capabilities.OutputReportByteLength];
8.2227 +
8.2228 + // Store the report ID in the first byte of the buffer:
8.2229 +
8.2230 + outputReportBuffer[0] = 0;
8.2231 +
8.2232 + // Store the report data following the report ID.
8.2233 + // Use the data in the combo boxes on the form.
8.2234 +
8.2235 + outputReportBuffer[1] = Convert.ToByte(CboByte0.SelectedIndex);
8.2236 +
8.2237 + if (outputReportBuffer.GetUpperBound(0) > 1)
8.2238 + {
8.2239 + outputReportBuffer[2] = Convert.ToByte(CboByte1.SelectedIndex);
8.2240 + }
8.2241 +
8.2242 + // Write a report.
8.2243 +
8.2244 + Boolean success;
8.2245 +
8.2246 + if (_transferType.Equals(TransferTypes.Control))
8.2247 + {
8.2248 + {
8.2249 + _transferInProgress = true;
8.2250 +
8.2251 + // Use a control transfer to send the report,
8.2252 + // even if the HID has an interrupt OUT endpoint.
8.2253 +
8.2254 + success = _myHid.SendOutputReportViaControlTransfer(_hidHandle, outputReportBuffer);
8.2255 +
8.2256 + _transferInProgress = false;
8.2257 + cmdSendOutputReportControl.Enabled = true;
8.2258 + }
8.2259 + }
8.2260 + else
8.2261 + {
8.2262 + Debug.Print("interrupt");
8.2263 + _transferInProgress = true;
8.2264 +
8.2265 + // The CancellationTokenSource specifies the timeout value and the action to take on a timeout.
8.2266 +
8.2267 + var cts = new CancellationTokenSource();
8.2268 +
8.2269 + // Create a delegate to execute on a timeout.
8.2270 +
8.2271 + Action onWriteTimeoutAction = OnWriteTimeout;
8.2272 +
8.2273 + // Cancel the read if it hasn't completed after a timeout.
8.2274 +
8.2275 + cts.CancelAfter(writeTimeout);
8.2276 +
8.2277 + // Specify the function to call on a timeout.
8.2278 +
8.2279 + cts.Token.Register(onWriteTimeoutAction);
8.2280 +
8.2281 + // Send an Output report and wait for completion or timeout.
8.2282 +
8.2283 + success = await _myHid.SendOutputReportViaInterruptTransfer(_deviceData, _hidHandle, outputReportBuffer, cts);
8.2284 +
8.2285 + // Get here only if the operation completes without a timeout.
8.2286 +
8.2287 + _transferInProgress = false;
8.2288 + cmdSendOutputReportInterrupt.Enabled = true;
8.2289 +
8.2290 + // Dispose to stop the timeout timer.
8.2291 +
8.2292 + cts.Dispose();
8.2293 + }
8.2294 + if (success)
8.2295 + {
8.2296 + DisplayReportData(outputReportBuffer, ReportTypes.Output, ReportReadOrWritten.Written);
8.2297 + }
8.2298 + else
8.2299 + {
8.2300 + CloseCommunications();
8.2301 + AccessForm(FormActions.AddItemToListBox, "The attempt to write an Output report failed.");
8.2302 + ScrollToBottomOfListBox();
8.2303 + }
8.2304 + }
8.2305 + }
8.2306 + else
8.2307 + {
8.2308 + AccessForm(FormActions.AddItemToListBox, "The HID doesn't have an Output report.");
8.2309 + }
8.2310 + }
8.2311 +
8.2312 + catch (Exception ex)
8.2313 + {
8.2314 + DisplayException(Name, ex);
8.2315 + throw;
8.2316 + }
8.2317 + }
8.2318 +
8.2319 + /// <summary>
8.2320 + /// Scroll to the bottom of the list box and trim as needed.
8.2321 + /// </summary>
8.2322 +
8.2323 + private void ScrollToBottomOfListBox()
8.2324 + {
8.2325 + try
8.2326 + {
8.2327 + LstResults.SelectedIndex = LstResults.Items.Count - 1;
8.2328 +
8.2329 + // If the list box is getting too large, trim its contents by removing the earliest data.
8.2330 +
8.2331 + if (LstResults.Items.Count > 1000)
8.2332 + {
8.2333 + Int32 count;
8.2334 + for (count = 1; count <= 500; count++)
8.2335 + {
8.2336 + LstResults.Items.RemoveAt(4);
8.2337 + }
8.2338 + }
8.2339 + }
8.2340 + catch (Exception ex)
8.2341 + {
8.2342 + DisplayException(Name, ex);
8.2343 + throw;
8.2344 + }
8.2345 + }
8.2346 +
8.2347 + /// <summary>
8.2348 + /// Request to send or get a Feature report.
8.2349 + /// </summary>
8.2350 +
8.2351 + private void SendOrGetFeatureReport()
8.2352 + {
8.2353 + try
8.2354 + {
8.2355 + // If the device hasn't been detected, was removed, or timed out on a previous attempt
8.2356 + // to access it, look for the device.
8.2357 +
8.2358 + if (!_deviceHandleObtained)
8.2359 + {
8.2360 + _deviceHandleObtained = FindTheHid();
8.2361 + }
8.2362 +
8.2363 + if (_deviceHandleObtained)
8.2364 + {
8.2365 + switch (_sendOrGet)
8.2366 + {
8.2367 + case SendOrGet.Send:
8.2368 + RequestToSendFeatureReport();
8.2369 + _sendOrGet = SendOrGet.Get;
8.2370 + break;
8.2371 + case SendOrGet.Get:
8.2372 + RequestToGetFeatureReport();
8.2373 + _sendOrGet = SendOrGet.Send;
8.2374 + break;
8.2375 + }
8.2376 + }
8.2377 + }
8.2378 + catch (Exception ex)
8.2379 + {
8.2380 + DisplayException(Name, ex);
8.2381 + throw;
8.2382 + }
8.2383 + }
8.2384 +
8.2385 + /// <summary>
8.2386 + /// Request to send an Output report or get an Input report.
8.2387 + /// </summary>
8.2388 +
8.2389 + private void SendOutputReportOrGetInputReport()
8.2390 + {
8.2391 + try
8.2392 + {
8.2393 + // If the device hasn't been detected, was removed, or timed out on a previous attempt
8.2394 + // to access it, look for the device.
8.2395 +
8.2396 + if (!_deviceHandleObtained)
8.2397 + {
8.2398 + _deviceHandleObtained = FindTheHid();
8.2399 + }
8.2400 +
8.2401 + if (_deviceHandleObtained)
8.2402 + {
8.2403 + if (_sendOrGet == SendOrGet.Send)
8.2404 + {
8.2405 + RequestToSendOutputReport();
8.2406 + _sendOrGet = SendOrGet.Get;
8.2407 + }
8.2408 + else
8.2409 + {
8.2410 + RequestToGetInputReport();
8.2411 + _sendOrGet = SendOrGet.Send;
8.2412 + }
8.2413 + }
8.2414 + }
8.2415 + catch (Exception ex)
8.2416 + {
8.2417 + DisplayException(Name, ex);
8.2418 + throw;
8.2419 + }
8.2420 + }
8.2421 +
8.2422 + /// <summary>
8.2423 + /// Set the number of Input buffers (the number of Input reports
8.2424 + /// the host will store) from the value in the text box.
8.2425 + /// </summary>
8.2426 +
8.2427 + private void SetInputReportBufferSize()
8.2428 + {
8.2429 + try
8.2430 + {
8.2431 + if (!_transferInProgress)
8.2432 + {
8.2433 + // Get the number of buffers from the text box.
8.2434 +
8.2435 + Int32 numberOfInputBuffers = Convert.ToInt32(txtInputReportBufferSize.Text);
8.2436 +
8.2437 + // Set the number of buffers.
8.2438 +
8.2439 + _myHid.SetNumberOfInputBuffers(_hidHandle, numberOfInputBuffers);
8.2440 +
8.2441 + // Verify and display the result.
8.2442 +
8.2443 + GetInputReportBufferSize();
8.2444 + }
8.2445 + else
8.2446 + {
8.2447 + DisplayTransferInProgressMessage();
8.2448 + }
8.2449 + }
8.2450 + catch (Exception ex)
8.2451 + {
8.2452 + DisplayException(Name, ex);
8.2453 + throw;
8.2454 + }
8.2455 + }
8.2456 +
8.2457 + /// <summary>
8.2458 + /// Perform actions that must execute when the program ends.
8.2459 + /// </summary>
8.2460 +
8.2461 + private void Shutdown()
8.2462 + {
8.2463 + try
8.2464 + {
8.2465 + CloseCommunications();
8.2466 + DeviceNotificationsStop();
8.2467 + }
8.2468 + catch (Exception ex)
8.2469 + {
8.2470 + DisplayException(Name, ex);
8.2471 + throw;
8.2472 + }
8.2473 + }
8.2474 +
8.2475 + /// <summary>
8.2476 + /// Perform actions that must execute when the program starts.
8.2477 + /// </summary>
8.2478 +
8.2479 + private void Startup()
8.2480 + {
8.2481 + const Int32 periodicTransferInterval = 1000;
8.2482 + try
8.2483 + {
8.2484 + _myHid = new Hid();
8.2485 + InitializeDisplay();
8.2486 +
8.2487 + _periodicTransfers = new System.Timers.Timer(periodicTransferInterval);
8.2488 + _periodicTransfers.Elapsed += DoPeriodicTransfers;
8.2489 + _periodicTransfers.Stop();
8.2490 + _periodicTransfers.SynchronizingObject = this;
8.2491 +
8.2492 + // Default USB Vendor ID and Product ID:
8.2493 +
8.2494 + txtVendorID.Text = "0925";
8.2495 + txtProductID.Text = "7001";
8.2496 +
8.2497 + GetVendorAndProductIDsFromTextBoxes(ref _myVendorId, ref _myProductId);
8.2498 +
8.2499 + DeviceNotificationsStart();
8.2500 + FindDeviceUsingWmi();
8.2501 + FindTheHid();
8.2502 + }
8.2503 + catch (Exception ex)
8.2504 + {
8.2505 + DisplayException(Name, ex);
8.2506 + throw;
8.2507 + }
8.2508 + }
8.2509 +
8.2510 + /// <summary>
8.2511 + /// The Product ID has changed in the text box. Call a routine to handle it.
8.2512 + /// </summary>
8.2513 +
8.2514 + private void txtProductID_TextChanged(Object sender, EventArgs e)
8.2515 + {
8.2516 + try
8.2517 + {
8.2518 + DeviceHasChanged();
8.2519 + }
8.2520 + catch (Exception ex)
8.2521 + {
8.2522 + DisplayException(Name, ex);
8.2523 + throw;
8.2524 + }
8.2525 + }
8.2526 +
8.2527 + /// <summary>
8.2528 + /// The Vendor ID has changed in the text box. Call a routine to handle it.
8.2529 + /// </summary>
8.2530 +
8.2531 + private void txtVendorID_TextChanged(Object sender, EventArgs e)
8.2532 + {
8.2533 + try
8.2534 + {
8.2535 + DeviceHasChanged();
8.2536 + }
8.2537 + catch (Exception ex)
8.2538 + {
8.2539 + DisplayException(Name, ex);
8.2540 + throw;
8.2541 + }
8.2542 + }
8.2543 +
8.2544 + /// <summary>
8.2545 + /// Provides a central mechanism for exception handling.
8.2546 + /// Displays a message box that describes the exception.
8.2547 + /// </summary>
8.2548 + ///
8.2549 + /// <param name="moduleName"> the module where the exception occurred. </param>
8.2550 + /// <param name="e"> the exception </param>
8.2551 +
8.2552 + internal static void DisplayException(String moduleName, Exception e)
8.2553 + {
8.2554 + // Create an error message.
8.2555 +
8.2556 + String message = "Exception: " + e.Message + Environment.NewLine + "Module: " + moduleName + Environment.NewLine + "Method: " + e.TargetSite.Name;
8.2557 +
8.2558 + const String caption = "Unexpected Exception";
8.2559 +
8.2560 + MessageBox.Show(message, caption, MessageBoxButtons.OK);
8.2561 + Debug.Write(message);
8.2562 +
8.2563 + // Get the last error and display it.
8.2564 +
8.2565 + Int32 error = Marshal.GetLastWin32Error();
8.2566 +
8.2567 + Debug.WriteLine("The last Win32 Error was: " + error);
8.2568 + }
8.2569 +
8.2570 + [STAThread]
8.2571 + internal static void Main() { Application.Run(new FrmMain()); }
8.2572 + private static FrmMain _transDefaultFormFrmMain;
8.2573 + internal static FrmMain TransDefaultFormFrmMain
8.2574 + {
8.2575 + get
8.2576 + {
8.2577 + if (_transDefaultFormFrmMain == null)
8.2578 + {
8.2579 + _transDefaultFormFrmMain = new FrmMain();
8.2580 + }
8.2581 + return _transDefaultFormFrmMain;
8.2582 + }
8.2583 + }
8.2584 + }
8.2585 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/FrmMain.resX Wed May 14 07:52:21 2014 +0200
9.3 @@ -0,0 +1,126 @@
9.4 +<?xml version="1.0" encoding="utf-8"?>
9.5 +<root>
9.6 + <!--
9.7 + Microsoft ResX Schema
9.8 +
9.9 + Version 2.0
9.10 +
9.11 + The primary goals of this format is to allow a simple XML format
9.12 + that is mostly human readable. The generation and parsing of the
9.13 + various data types are done through the TypeConverter classes
9.14 + associated with the data types.
9.15 +
9.16 + Example:
9.17 +
9.18 + ... ado.net/XML headers & schema ...
9.19 + <resheader name="resmimetype">text/microsoft-resx</resheader>
9.20 + <resheader name="version">2.0</resheader>
9.21 + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
9.22 + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
9.23 + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
9.24 + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
9.25 + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
9.26 + <value>[base64 mime encoded serialized .NET Framework object]</value>
9.27 + </data>
9.28 + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
9.29 + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
9.30 + <comment>This is a comment</comment>
9.31 + </data>
9.32 +
9.33 + There are any number of "resheader" rows that contain simple
9.34 + name/value pairs.
9.35 +
9.36 + Each data row contains a name, and value. The row also contains a
9.37 + type or mimetype. Type corresponds to a .NET class that support
9.38 + text/value conversion through the TypeConverter architecture.
9.39 + Classes that don't support this are serialized and stored with the
9.40 + mimetype set.
9.41 +
9.42 + The mimetype is used for serialized objects, and tells the
9.43 + ResXResourceReader how to depersist the object. This is currently not
9.44 + extensible. For a given mimetype the value must be set accordingly:
9.45 +
9.46 + Note - application/x-microsoft.net.object.binary.base64 is the format
9.47 + that the ResXResourceWriter will generate, however the reader can
9.48 + read any of the formats listed below.
9.49 +
9.50 + mimetype: application/x-microsoft.net.object.binary.base64
9.51 + value : The object must be serialized with
9.52 + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
9.53 + : and then encoded with base64 encoding.
9.54 +
9.55 + mimetype: application/x-microsoft.net.object.soap.base64
9.56 + value : The object must be serialized with
9.57 + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
9.58 + : and then encoded with base64 encoding.
9.59 +
9.60 + mimetype: application/x-microsoft.net.object.bytearray.base64
9.61 + value : The object must be serialized into a byte array
9.62 + : using a System.ComponentModel.TypeConverter
9.63 + : and then encoded with base64 encoding.
9.64 + -->
9.65 + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
9.66 + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
9.67 + <xsd:element name="root" msdata:IsDataSet="true">
9.68 + <xsd:complexType>
9.69 + <xsd:choice maxOccurs="unbounded">
9.70 + <xsd:element name="metadata">
9.71 + <xsd:complexType>
9.72 + <xsd:sequence>
9.73 + <xsd:element name="value" type="xsd:string" minOccurs="0" />
9.74 + </xsd:sequence>
9.75 + <xsd:attribute name="name" use="required" type="xsd:string" />
9.76 + <xsd:attribute name="type" type="xsd:string" />
9.77 + <xsd:attribute name="mimetype" type="xsd:string" />
9.78 + <xsd:attribute ref="xml:space" />
9.79 + </xsd:complexType>
9.80 + </xsd:element>
9.81 + <xsd:element name="assembly">
9.82 + <xsd:complexType>
9.83 + <xsd:attribute name="alias" type="xsd:string" />
9.84 + <xsd:attribute name="name" type="xsd:string" />
9.85 + </xsd:complexType>
9.86 + </xsd:element>
9.87 + <xsd:element name="data">
9.88 + <xsd:complexType>
9.89 + <xsd:sequence>
9.90 + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
9.91 + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
9.92 + </xsd:sequence>
9.93 + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
9.94 + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
9.95 + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
9.96 + <xsd:attribute ref="xml:space" />
9.97 + </xsd:complexType>
9.98 + </xsd:element>
9.99 + <xsd:element name="resheader">
9.100 + <xsd:complexType>
9.101 + <xsd:sequence>
9.102 + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
9.103 + </xsd:sequence>
9.104 + <xsd:attribute name="name" type="xsd:string" use="required" />
9.105 + </xsd:complexType>
9.106 + </xsd:element>
9.107 + </xsd:choice>
9.108 + </xsd:complexType>
9.109 + </xsd:element>
9.110 + </xsd:schema>
9.111 + <resheader name="resmimetype">
9.112 + <value>text/microsoft-resx</value>
9.113 + </resheader>
9.114 + <resheader name="version">
9.115 + <value>2.0</value>
9.116 + </resheader>
9.117 + <resheader name="reader">
9.118 + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
9.119 + </resheader>
9.120 + <resheader name="writer">
9.121 + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
9.122 + </resheader>
9.123 + <metadata name="ToolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
9.124 + <value>17, 17</value>
9.125 + </metadata>
9.126 + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
9.127 + <value>25</value>
9.128 + </metadata>
9.129 +</root>
9.130 \ No newline at end of file
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/GenericHid.cs Wed May 14 07:52:21 2014 +0200
10.3 @@ -0,0 +1,24 @@
10.4 +
10.5 +using System.Windows.Forms;
10.6 +
10.7 +namespace GenericHid
10.8 +{
10.9 + /// <summary>
10.10 + /// Runs the application and provides access to the instance of the form.
10.11 + /// </summary>
10.12 +
10.13 + public class GenericHid
10.14 + {
10.15 + internal static FrmMain FrmMy;
10.16 +
10.17 + /// <summary>
10.18 + /// Displays the application's main form.
10.19 + /// </summary>
10.20 +
10.21 + public static void Main()
10.22 + {
10.23 + FrmMy = new FrmMain();
10.24 + Application.Run(FrmMy);
10.25 + }
10.26 + }
10.27 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/GenericHid.csproj Wed May 14 07:52:21 2014 +0200
11.3 @@ -0,0 +1,194 @@
11.4 +<?xml version="1.0" encoding="utf-8"?>
11.5 +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
11.6 + <PropertyGroup>
11.7 + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
11.8 + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
11.9 + <ProductVersion>9.0.30729</ProductVersion>
11.10 + <SchemaVersion>2.0</SchemaVersion>
11.11 + <ProjectGuid>{A6E0F52F-4599-4758-B956-9E8420FD28A8}</ProjectGuid>
11.12 + <OutputType>WinExe</OutputType>
11.13 + <AppDesignerFolder>Properties</AppDesignerFolder>
11.14 + <RootNamespace>GenericHid</RootNamespace>
11.15 + <AssemblyName>GenericHid</AssemblyName>
11.16 + <StartupObject>GenericHid.FrmMain</StartupObject>
11.17 + <FileUpgradeFlags>
11.18 + </FileUpgradeFlags>
11.19 + <OldToolsVersion>3.5</OldToolsVersion>
11.20 + <UpgradeBackupLocation>
11.21 + </UpgradeBackupLocation>
11.22 + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
11.23 + <TargetFrameworkProfile />
11.24 + <IsWebBootstrapper>false</IsWebBootstrapper>
11.25 + <PublishUrl>publish\</PublishUrl>
11.26 + <Install>true</Install>
11.27 + <InstallFrom>Disk</InstallFrom>
11.28 + <UpdateEnabled>false</UpdateEnabled>
11.29 + <UpdateMode>Foreground</UpdateMode>
11.30 + <UpdateInterval>7</UpdateInterval>
11.31 + <UpdateIntervalUnits>Days</UpdateIntervalUnits>
11.32 + <UpdatePeriodically>false</UpdatePeriodically>
11.33 + <UpdateRequired>false</UpdateRequired>
11.34 + <MapFileExtensions>true</MapFileExtensions>
11.35 + <ApplicationRevision>0</ApplicationRevision>
11.36 + <ApplicationVersion>6.2.0.0</ApplicationVersion>
11.37 + <UseApplicationTrust>false</UseApplicationTrust>
11.38 + <PublishWizardCompleted>true</PublishWizardCompleted>
11.39 + <BootstrapperEnabled>true</BootstrapperEnabled>
11.40 + </PropertyGroup>
11.41 + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
11.42 + <DebugSymbols>true</DebugSymbols>
11.43 + <DebugType>full</DebugType>
11.44 + <Optimize>false</Optimize>
11.45 + <OutputPath>bin\Debug\</OutputPath>
11.46 + <DefineConstants>DEBUG;TRACE</DefineConstants>
11.47 + <ErrorReport>prompt</ErrorReport>
11.48 + <WarningLevel>2</WarningLevel>
11.49 + <BaseAddress>285212672</BaseAddress>
11.50 + <Prefer32Bit>false</Prefer32Bit>
11.51 + </PropertyGroup>
11.52 + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
11.53 + <DebugType>pdbonly</DebugType>
11.54 + <Optimize>false</Optimize>
11.55 + <OutputPath>bin\Release\</OutputPath>
11.56 + <DefineConstants>TRACE</DefineConstants>
11.57 + <ErrorReport>prompt</ErrorReport>
11.58 + <WarningLevel>2</WarningLevel>
11.59 + <BaseAddress>285212672</BaseAddress>
11.60 + <Prefer32Bit>false</Prefer32Bit>
11.61 + </PropertyGroup>
11.62 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
11.63 + <DebugSymbols>true</DebugSymbols>
11.64 + <OutputPath>bin\x86\Debug\</OutputPath>
11.65 + <DefineConstants>DEBUG;TRACE</DefineConstants>
11.66 + <BaseAddress>285212672</BaseAddress>
11.67 + <WarningLevel>2</WarningLevel>
11.68 + <DebugType>full</DebugType>
11.69 + <PlatformTarget>x86</PlatformTarget>
11.70 + <ErrorReport>prompt</ErrorReport>
11.71 + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
11.72 + </PropertyGroup>
11.73 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
11.74 + <OutputPath>bin\x86\Release\</OutputPath>
11.75 + <DefineConstants>TRACE</DefineConstants>
11.76 + <BaseAddress>285212672</BaseAddress>
11.77 + <WarningLevel>2</WarningLevel>
11.78 + <DebugType>pdbonly</DebugType>
11.79 + <PlatformTarget>x86</PlatformTarget>
11.80 + <ErrorReport>prompt</ErrorReport>
11.81 + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
11.82 + </PropertyGroup>
11.83 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
11.84 + <DebugSymbols>true</DebugSymbols>
11.85 + <OutputPath>bin\x64\Debug\</OutputPath>
11.86 + <DefineConstants>DEBUG;TRACE</DefineConstants>
11.87 + <BaseAddress>285212672</BaseAddress>
11.88 + <WarningLevel>2</WarningLevel>
11.89 + <DebugType>full</DebugType>
11.90 + <PlatformTarget>x64</PlatformTarget>
11.91 + <ErrorReport>prompt</ErrorReport>
11.92 + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
11.93 + </PropertyGroup>
11.94 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
11.95 + <OutputPath>bin\x64\Release\</OutputPath>
11.96 + <DefineConstants>TRACE</DefineConstants>
11.97 + <BaseAddress>285212672</BaseAddress>
11.98 + <WarningLevel>2</WarningLevel>
11.99 + <DebugType>pdbonly</DebugType>
11.100 + <PlatformTarget>x64</PlatformTarget>
11.101 + <ErrorReport>prompt</ErrorReport>
11.102 + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
11.103 + </PropertyGroup>
11.104 + <PropertyGroup>
11.105 + <ManifestCertificateThumbprint>74AEA279A1F2ABCF00D2AB2668EE07AB57384C56</ManifestCertificateThumbprint>
11.106 + </PropertyGroup>
11.107 + <PropertyGroup>
11.108 + <ManifestKeyFile>GenericHid_TemporaryKey.pfx</ManifestKeyFile>
11.109 + </PropertyGroup>
11.110 + <PropertyGroup>
11.111 + <GenerateManifests>true</GenerateManifests>
11.112 + </PropertyGroup>
11.113 + <PropertyGroup>
11.114 + <SignManifests>true</SignManifests>
11.115 + </PropertyGroup>
11.116 + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
11.117 + <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
11.118 + Other similar extension points exist, see Microsoft.Common.targets.
11.119 + <Target Name="BeforeBuild">
11.120 + </Target>
11.121 + <Target Name="AfterBuild">
11.122 + </Target>
11.123 + -->
11.124 + <ItemGroup>
11.125 + <Reference Include="microsoft.visualbasic" />
11.126 + <Reference Include="System" />
11.127 + <Reference Include="System.Data" />
11.128 + <Reference Include="System.Drawing" />
11.129 + <Reference Include="System.Management" />
11.130 + <Reference Include="System.Windows.Forms" />
11.131 + <Reference Include="System.Xml" />
11.132 + </ItemGroup>
11.133 + <ItemGroup>
11.134 + <Compile Include="AssemblyInfo.cs" />
11.135 + <Compile Include="Debugging.cs" />
11.136 + <Compile Include="DebuggingDeclarations.cs" />
11.137 + <Compile Include="DeviceManagement.cs" />
11.138 + <Compile Include="DeviceManagementDeclarations.cs" />
11.139 + <Compile Include="FileIODeclarations.cs" />
11.140 + <Compile Include="FrmMain.cs">
11.141 + <SubType>Form</SubType>
11.142 + </Compile>
11.143 + <Compile Include="GenericHid.cs" />
11.144 + <Compile Include="Hid.cs" />
11.145 + <Compile Include="HidDeclarations.cs" />
11.146 + <Compile Include="Properties\Resources.Designer.cs">
11.147 + <AutoGen>True</AutoGen>
11.148 + <DesignTime>True</DesignTime>
11.149 + <DependentUpon>Resources.resx</DependentUpon>
11.150 + </Compile>
11.151 + <Compile Include="Properties\Settings.Designer.cs">
11.152 + <AutoGen>True</AutoGen>
11.153 + <DesignTimeSharedInput>True</DesignTimeSharedInput>
11.154 + <DependentUpon>Settings.settings</DependentUpon>
11.155 + </Compile>
11.156 + </ItemGroup>
11.157 + <ItemGroup>
11.158 + <EmbeddedResource Include="FrmMain.resX">
11.159 + <SubType>Designer</SubType>
11.160 + <DependentUpon>FrmMain.cs</DependentUpon>
11.161 + </EmbeddedResource>
11.162 + <EmbeddedResource Include="Properties\Resources.resx">
11.163 + <SubType>Designer</SubType>
11.164 + <Generator>ResXFileCodeGenerator</Generator>
11.165 + <LastGenOutput>Resources.Designer.cs</LastGenOutput>
11.166 + </EmbeddedResource>
11.167 + </ItemGroup>
11.168 + <ItemGroup>
11.169 + <None Include="app.config" />
11.170 + <None Include="ClassDiagram1.cd" />
11.171 + <None Include="GenericHid_TemporaryKey.pfx" />
11.172 + <None Include="Properties\Settings.settings">
11.173 + <Generator>SettingsSingleFileGenerator</Generator>
11.174 + <LastGenOutput>Settings.Designer.cs</LastGenOutput>
11.175 + </None>
11.176 + </ItemGroup>
11.177 + <ItemGroup>
11.178 + <Content Include="readme.txt" />
11.179 + </ItemGroup>
11.180 + <ItemGroup>
11.181 + <BootstrapperPackage Include=".NETFramework,Version=v4.5">
11.182 + <Visible>False</Visible>
11.183 + <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
11.184 + <Install>true</Install>
11.185 + </BootstrapperPackage>
11.186 + <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
11.187 + <Visible>False</Visible>
11.188 + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
11.189 + <Install>false</Install>
11.190 + </BootstrapperPackage>
11.191 + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
11.192 + <Visible>False</Visible>
11.193 + <ProductName>.NET Framework 3.5 SP1</ProductName>
11.194 + <Install>false</Install>
11.195 + </BootstrapperPackage>
11.196 + </ItemGroup>
11.197 +</Project>
11.198 \ No newline at end of file
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/GenericHid.csproj.user Wed May 14 07:52:21 2014 +0200
12.3 @@ -0,0 +1,31 @@
12.4 +<?xml version="1.0" encoding="utf-8"?>
12.5 +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
12.6 + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
12.7 + <StartWithIE>true</StartWithIE>
12.8 + </PropertyGroup>
12.9 + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
12.10 + <StartWithIE>true</StartWithIE>
12.11 + </PropertyGroup>
12.12 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
12.13 + <StartWithIE>true</StartWithIE>
12.14 + </PropertyGroup>
12.15 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
12.16 + <StartWithIE>true</StartWithIE>
12.17 + </PropertyGroup>
12.18 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
12.19 + <StartWithIE>true</StartWithIE>
12.20 + </PropertyGroup>
12.21 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
12.22 + <StartWithIE>true</StartWithIE>
12.23 + </PropertyGroup>
12.24 + <PropertyGroup>
12.25 + <PublishUrlHistory>publish\</PublishUrlHistory>
12.26 + <InstallUrlHistory />
12.27 + <SupportUrlHistory />
12.28 + <UpdateUrlHistory />
12.29 + <BootstrapperUrlHistory />
12.30 + <ErrorReportUrlHistory />
12.31 + <FallbackCulture>en-US</FallbackCulture>
12.32 + <VerifyUploadedFiles>false</VerifyUploadedFiles>
12.33 + </PropertyGroup>
12.34 +</Project>
12.35 \ No newline at end of file
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/Generic_Hid_cs_v62.sln Wed May 14 07:52:21 2014 +0200
13.3 @@ -0,0 +1,32 @@
13.4 +
13.5 +Microsoft Visual Studio Solution File, Format Version 12.00
13.6 +# Visual Studio 2012
13.7 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenericHid", "GenericHid.csproj", "{A6E0F52F-4599-4758-B956-9E8420FD28A8}"
13.8 +EndProject
13.9 +Global
13.10 + GlobalSection(SolutionConfigurationPlatforms) = preSolution
13.11 + Debug|Any CPU = Debug|Any CPU
13.12 + Debug|x64 = Debug|x64
13.13 + Debug|x86 = Debug|x86
13.14 + Release|Any CPU = Release|Any CPU
13.15 + Release|x64 = Release|x64
13.16 + Release|x86 = Release|x86
13.17 + EndGlobalSection
13.18 + GlobalSection(ProjectConfigurationPlatforms) = postSolution
13.19 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13.20 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
13.21 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Debug|x64.ActiveCfg = Debug|x64
13.22 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Debug|x64.Build.0 = Debug|x64
13.23 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Debug|x86.ActiveCfg = Debug|x86
13.24 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Debug|x86.Build.0 = Debug|x86
13.25 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
13.26 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Release|Any CPU.Build.0 = Release|Any CPU
13.27 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Release|x64.ActiveCfg = Debug|x64
13.28 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Release|x64.Build.0 = Debug|x64
13.29 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Release|x86.ActiveCfg = Release|x86
13.30 + {A6E0F52F-4599-4758-B956-9E8420FD28A8}.Release|x86.Build.0 = Release|x86
13.31 + EndGlobalSection
13.32 + GlobalSection(SolutionProperties) = preSolution
13.33 + HideSolutionNode = FALSE
13.34 + EndGlobalSection
13.35 +EndGlobal
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/Hid.cs Wed May 14 07:52:21 2014 +0200
14.3 @@ -0,0 +1,739 @@
14.4 +using Microsoft.Win32.SafeHandles;
14.5 +using System;
14.6 +using System.Diagnostics;
14.7 +using System.IO;
14.8 +using System.Runtime.InteropServices;
14.9 +using System.Threading;
14.10 +using System.Threading.Tasks;
14.11 +using System.Windows.Forms;
14.12 +
14.13 +namespace GenericHid
14.14 +{
14.15 + /// <summary>
14.16 + /// Supports Windows API functions for accessing HID-class USB devices.
14.17 + /// Includes routines for retrieving information about the configuring a HID and
14.18 + /// sending and receiving reports via control and interrupt transfers.
14.19 + /// </summary>
14.20 +
14.21 + internal sealed partial class Hid
14.22 + {
14.23 + // Used in error messages.
14.24 +
14.25 + private const String ModuleName = "Hid";
14.26 +
14.27 + internal NativeMethods.HIDP_CAPS Capabilities;
14.28 + internal NativeMethods.HIDD_ATTRIBUTES DeviceAttributes;
14.29 +
14.30 + // For viewing results of API calls in debug.write statements:
14.31 +
14.32 + internal static Debugging MyDebugging = new Debugging();
14.33 +
14.34 + /// <summary>
14.35 + /// Provides a central mechanism for exception handling.
14.36 + /// Displays a message box that describes the exception.
14.37 + /// </summary>
14.38 + ///
14.39 + /// <param name="moduleName"> the module where the exception occurred. </param>
14.40 + /// <param name="e"> the exception </param>
14.41 +
14.42 + internal static void DisplayException(String moduleName, Exception e)
14.43 + {
14.44 + // Create an error message.
14.45 +
14.46 + String message = "Exception: " + e.Message + Environment.NewLine + "Module: " + moduleName + Environment.NewLine + "Method: " + e.TargetSite.Name;
14.47 +
14.48 + const String caption = "Unexpected Exception";
14.49 +
14.50 + MessageBox.Show(message, caption, MessageBoxButtons.OK);
14.51 + Debug.Write(message);
14.52 +
14.53 + // Get the last error and display it.
14.54 + Int32 error = Marshal.GetLastWin32Error();
14.55 +
14.56 + Debug.WriteLine("The last Win32 Error was: " + error);
14.57 + }
14.58 +
14.59 + /// <summary>
14.60 + /// Remove any Input reports waiting in the buffer.
14.61 + /// </summary>
14.62 + /// <param name="hidHandle"> a handle to a device. </param>
14.63 + /// <returns>
14.64 + /// True on success, False on failure.
14.65 + /// </returns>
14.66 +
14.67 + internal Boolean FlushQueue(SafeFileHandle hidHandle)
14.68 + {
14.69 + try
14.70 + {
14.71 + // ***
14.72 + // API function: HidD_FlushQueue
14.73 +
14.74 + // Purpose: Removes any Input reports waiting in the buffer.
14.75 +
14.76 + // Accepts: a handle to the device.
14.77 +
14.78 + // Returns: True on success, False on failure.
14.79 + // ***
14.80 +
14.81 + Boolean success = NativeMethods.HidD_FlushQueue(hidHandle);
14.82 +
14.83 + return success;
14.84 + }
14.85 +
14.86 + catch (Exception ex)
14.87 + {
14.88 + DisplayException(ModuleName, ex);
14.89 + throw;
14.90 + }
14.91 + }
14.92 +
14.93 + /// <summary>
14.94 + /// Get HID attributes.
14.95 + /// </summary>
14.96 + /// <param name="hidHandle"> HID handle retrieved with CreateFile </param>
14.97 + /// <param name="deviceAttributes"> HID attributes structure </param>
14.98 + /// <returns> true on success </returns>
14.99 +
14.100 + internal Boolean GetAttributes(SafeFileHandle hidHandle, ref NativeMethods.HIDD_ATTRIBUTES deviceAttributes)
14.101 + {
14.102 + Boolean success;
14.103 + try
14.104 + {
14.105 + // ***
14.106 + // API function:
14.107 + // HidD_GetAttributes
14.108 +
14.109 + // Purpose:
14.110 + // Retrieves a HIDD_ATTRIBUTES structure containing the Vendor ID,
14.111 + // Product ID, and Product Version Number for a device.
14.112 +
14.113 + // Accepts:
14.114 + // A handle returned by CreateFile.
14.115 + // A pointer to receive a HIDD_ATTRIBUTES structure.
14.116 +
14.117 + // Returns:
14.118 + // True on success, False on failure.
14.119 + // ***
14.120 +
14.121 + success = NativeMethods.HidD_GetAttributes(hidHandle, ref deviceAttributes);
14.122 + }
14.123 +
14.124 + catch (Exception ex)
14.125 + {
14.126 + DisplayException(ModuleName, ex);
14.127 + throw;
14.128 + }
14.129 + return success;
14.130 + }
14.131 +
14.132 + /// <summary>
14.133 + /// Retrieves a structure with information about a device's capabilities.
14.134 + /// </summary>
14.135 + ///
14.136 + /// <param name="hidHandle"> a handle to a device. </param>
14.137 + ///
14.138 + /// <returns>
14.139 + /// An HIDP_CAPS structure.
14.140 + /// </returns>
14.141 +
14.142 + internal NativeMethods.HIDP_CAPS GetDeviceCapabilities(SafeFileHandle hidHandle)
14.143 + {
14.144 + var preparsedData = new IntPtr();
14.145 +
14.146 + try
14.147 + {
14.148 + // ***
14.149 + // API function: HidD_GetPreparsedData
14.150 +
14.151 + // Purpose: retrieves a pointer to a buffer containing information about the device's capabilities.
14.152 + // HidP_GetCaps and other API functions require a pointer to the buffer.
14.153 +
14.154 + // Requires:
14.155 + // A handle returned by CreateFile.
14.156 + // A pointer to a buffer.
14.157 +
14.158 + // Returns:
14.159 + // True on success, False on failure.
14.160 + // ***
14.161 +
14.162 + NativeMethods.HidD_GetPreparsedData(hidHandle, ref preparsedData);
14.163 +
14.164 + // ***
14.165 + // API function: HidP_GetCaps
14.166 +
14.167 + // Purpose: find out a device's capabilities.
14.168 + // For standard devices such as joysticks, you can find out the specific
14.169 + // capabilities of the device.
14.170 + // For a custom device where the software knows what the device is capable of,
14.171 + // this call may be unneeded.
14.172 +
14.173 + // Accepts:
14.174 + // A pointer returned by HidD_GetPreparsedData
14.175 + // A pointer to a HIDP_CAPS structure.
14.176 +
14.177 + // Returns: True on success, False on failure.
14.178 + // ***
14.179 +
14.180 + Int32 result = NativeMethods.HidP_GetCaps(preparsedData, ref Capabilities);
14.181 + if ((result != 0))
14.182 + {
14.183 + Debug.WriteLine("");
14.184 + Debug.WriteLine(" Usage: " + Convert.ToString(Capabilities.Usage, 16));
14.185 + Debug.WriteLine(" Usage Page: " + Convert.ToString(Capabilities.UsagePage, 16));
14.186 + Debug.WriteLine(" Input Report Byte Length: " + Capabilities.InputReportByteLength);
14.187 + Debug.WriteLine(" Output Report Byte Length: " + Capabilities.OutputReportByteLength);
14.188 + Debug.WriteLine(" Feature Report Byte Length: " + Capabilities.FeatureReportByteLength);
14.189 + Debug.WriteLine(" Number of Link Collection Nodes: " + Capabilities.NumberLinkCollectionNodes);
14.190 + Debug.WriteLine(" Number of Input Button Caps: " + Capabilities.NumberInputButtonCaps);
14.191 + Debug.WriteLine(" Number of Input Value Caps: " + Capabilities.NumberInputValueCaps);
14.192 + Debug.WriteLine(" Number of Input Data Indices: " + Capabilities.NumberInputDataIndices);
14.193 + Debug.WriteLine(" Number of Output Button Caps: " + Capabilities.NumberOutputButtonCaps);
14.194 + Debug.WriteLine(" Number of Output Value Caps: " + Capabilities.NumberOutputValueCaps);
14.195 + Debug.WriteLine(" Number of Output Data Indices: " + Capabilities.NumberOutputDataIndices);
14.196 + Debug.WriteLine(" Number of Feature Button Caps: " + Capabilities.NumberFeatureButtonCaps);
14.197 + Debug.WriteLine(" Number of Feature Value Caps: " + Capabilities.NumberFeatureValueCaps);
14.198 + Debug.WriteLine(" Number of Feature Data Indices: " + Capabilities.NumberFeatureDataIndices);
14.199 +
14.200 + // ***
14.201 + // API function: HidP_GetValueCaps
14.202 +
14.203 + // Purpose: retrieves a buffer containing an array of HidP_ValueCaps structures.
14.204 + // Each structure defines the capabilities of one value.
14.205 + // This application doesn't use this data.
14.206 +
14.207 + // Accepts:
14.208 + // A report type enumerator from hidpi.h,
14.209 + // A pointer to a buffer for the returned array,
14.210 + // The NumberInputValueCaps member of the device's HidP_Caps structure,
14.211 + // A pointer to the PreparsedData structure returned by HidD_GetPreparsedData.
14.212 +
14.213 + // Returns: True on success, False on failure.
14.214 + // ***
14.215 +
14.216 + Int32 vcSize = Capabilities.NumberInputValueCaps;
14.217 + var valueCaps = new Byte[vcSize];
14.218 +
14.219 + NativeMethods.HidP_GetValueCaps(NativeMethods.HidP_Input, valueCaps, ref vcSize, preparsedData);
14.220 +
14.221 + // (To use this data, copy the ValueCaps byte array into an array of structures.)
14.222 + }
14.223 + }
14.224 +
14.225 + catch (Exception ex)
14.226 + {
14.227 + DisplayException(ModuleName, ex);
14.228 + throw;
14.229 + }
14.230 + finally
14.231 + {
14.232 + // ***
14.233 + // API function: HidD_FreePreparsedData
14.234 +
14.235 + // Purpose: frees the buffer reserved by HidD_GetPreparsedData.
14.236 +
14.237 + // Accepts: A pointer to the PreparsedData structure returned by HidD_GetPreparsedData.
14.238 +
14.239 + // Returns: True on success, False on failure.
14.240 + // ***
14.241 +
14.242 + if (preparsedData != IntPtr.Zero)
14.243 + {
14.244 + NativeMethods.HidD_FreePreparsedData(preparsedData);
14.245 + }
14.246 + }
14.247 + return Capabilities;
14.248 + }
14.249 +
14.250 + /// <summary>
14.251 + /// reads a Feature report from the device.
14.252 + /// </summary>
14.253 + ///
14.254 + /// <param name="hidHandle"> the handle for learning about the device and exchanging Feature reports. </param>
14.255 + /// <param name="inFeatureReportBuffer"> contains the requested report.</param>
14.256 +
14.257 + internal Boolean GetFeatureReport(SafeFileHandle hidHandle, ref Byte[] inFeatureReportBuffer)
14.258 + {
14.259 + try
14.260 + {
14.261 + Boolean success = false;
14.262 +
14.263 + // ***
14.264 + // API function: HidD_GetFeature
14.265 + // Attempts to read a Feature report from the device.
14.266 +
14.267 + // Requires:
14.268 + // A handle to a HID
14.269 + // A pointer to a buffer containing the report ID and report
14.270 + // The size of the buffer.
14.271 +
14.272 + // Returns: true on success, false on failure.
14.273 + // ***
14.274 +
14.275 + if (!hidHandle.IsInvalid && !hidHandle.IsClosed)
14.276 + {
14.277 + success = NativeMethods.HidD_GetFeature(hidHandle, inFeatureReportBuffer, inFeatureReportBuffer.Length);
14.278 +
14.279 + Debug.Print("HidD_GetFeature success = " + success);
14.280 + }
14.281 + return success;
14.282 + }
14.283 +
14.284 + catch (Exception ex)
14.285 + {
14.286 + DisplayException(ModuleName, ex);
14.287 + throw;
14.288 + }
14.289 + }
14.290 +
14.291 + /// <summary>
14.292 + /// Get the HID-class GUID
14.293 + /// </summary>
14.294 + /// <returns> the GUID </returns>
14.295 +
14.296 + internal Guid GetHidGuid()
14.297 + {
14.298 + Guid hidGuid = Guid.Empty;
14.299 + try
14.300 + {
14.301 + // ***
14.302 + // API function: 'HidD_GetHidGuid
14.303 +
14.304 + // Purpose: Retrieves the interface class GUID for the HID class.
14.305 +
14.306 + // Accepts: A System.Guid object for storing the GUID.
14.307 + // ***
14.308 +
14.309 + NativeMethods.HidD_GetHidGuid(ref hidGuid);
14.310 + }
14.311 +
14.312 + catch (Exception ex)
14.313 + {
14.314 + DisplayException(ModuleName, ex);
14.315 + throw;
14.316 + }
14.317 + return hidGuid;
14.318 + }
14.319 +
14.320 + /// <summary>
14.321 + /// Creates a 32-bit Usage from the Usage Page and Usage ID.
14.322 + /// Determines whether the Usage is a system mouse or keyboard.
14.323 + /// Can be modified to detect other Usages.
14.324 + /// </summary>
14.325 + ///
14.326 + /// <param name="myCapabilities"> a HIDP_CAPS structure retrieved with HidP_GetCaps. </param>
14.327 + ///
14.328 + /// <returns>
14.329 + /// A String describing the Usage.
14.330 + /// </returns>
14.331 +
14.332 + internal String GetHidUsage(NativeMethods.HIDP_CAPS myCapabilities)
14.333 + {
14.334 + String usageDescription = "";
14.335 +
14.336 + try
14.337 + {
14.338 + // Create32-bit Usage from Usage Page and Usage ID.
14.339 +
14.340 + Int32 usage = myCapabilities.UsagePage * 256 + myCapabilities.Usage;
14.341 +
14.342 + if (usage == Convert.ToInt32(0X102))
14.343 + {
14.344 + usageDescription = "mouse";
14.345 + }
14.346 + if (usage == Convert.ToInt32(0X106))
14.347 + {
14.348 + usageDescription = "keyboard";
14.349 + }
14.350 + }
14.351 +
14.352 + catch (Exception ex)
14.353 + {
14.354 + DisplayException(ModuleName, ex);
14.355 + throw;
14.356 + }
14.357 +
14.358 + return usageDescription;
14.359 + }
14.360 +
14.361 + /// <summary>
14.362 + /// reads an Input report from the device using a control transfer.
14.363 + /// </summary>
14.364 + /// <param name="hidHandle"> the handle for learning about the device and exchanging Feature reports. </param>
14.365 + /// <param name="inputReportBuffer"> contains the requested report. </param>
14.366 +
14.367 + internal Boolean GetInputReportViaControlTransfer(SafeFileHandle hidHandle, ref Byte[] inputReportBuffer)
14.368 + {
14.369 + var success = false;
14.370 +
14.371 + try
14.372 + {
14.373 + // ***
14.374 + // API function: HidD_GetInputReport
14.375 +
14.376 + // Purpose: Attempts to read an Input report from the device using a control transfer.
14.377 +
14.378 + // Requires:
14.379 + // A handle to a HID
14.380 + // A pointer to a buffer containing the report ID and report
14.381 + // The size of the buffer.
14.382 +
14.383 + // Returns: true on success, false on failure.
14.384 + // ***
14.385 +
14.386 + if (!hidHandle.IsInvalid && !hidHandle.IsClosed)
14.387 + {
14.388 + success = NativeMethods.HidD_GetInputReport(hidHandle, inputReportBuffer, inputReportBuffer.Length + 1);
14.389 + Debug.Print("HidD_GetInputReport success = " + success);
14.390 + }
14.391 + return success;
14.392 + }
14.393 +
14.394 + catch (Exception ex)
14.395 + {
14.396 + DisplayException(ModuleName, ex);
14.397 + throw;
14.398 + }
14.399 + }
14.400 +
14.401 + /// <summary>
14.402 + /// Reads an Input report from the device using an interrupt transfer.
14.403 + /// </summary>
14.404 + ///
14.405 + /// <param name="deviceData"> the Filestream for writing data. </param>
14.406 + /// <param name="inputReportBuffer"> contains the report ID and report data. </param>
14.407 + /// <returns>
14.408 + /// True on success. False on failure.
14.409 + /// </returns>
14.410 +
14.411 + internal async Task<Int32> GetInputReportViaInterruptTransfer(FileStream deviceData, Byte[] inputReportBuffer, CancellationTokenSource cts)
14.412 + {
14.413 + try
14.414 + {
14.415 + Int32 bytesRead = 0;
14.416 +
14.417 + // Begin reading an Input report.
14.418 +
14.419 + Task<Int32> t = deviceData.ReadAsync(inputReportBuffer, 0, inputReportBuffer.Length, cts.Token);
14.420 +
14.421 + bytesRead = await t;
14.422 +
14.423 + // Gets to here only if the read operation completed before a timeout.
14.424 +
14.425 + Debug.Print("Asynchronous read completed. Bytes read = " + Convert.ToString(bytesRead));
14.426 +
14.427 + // The operation has one of these completion states:
14.428 +
14.429 + switch (t.Status)
14.430 + {
14.431 + case TaskStatus.RanToCompletion:
14.432 + Debug.Print("Input report received from device");
14.433 + break;
14.434 + case TaskStatus.Canceled:
14.435 + Debug.Print("Task canceled");
14.436 + break;
14.437 + case TaskStatus.Faulted:
14.438 + Debug.Print("Unhandled exception");
14.439 + break;
14.440 + }
14.441 + return bytesRead;
14.442 + }
14.443 + catch (Exception ex)
14.444 + {
14.445 + DisplayException(ModuleName, ex);
14.446 + throw;
14.447 + }
14.448 + }
14.449 +
14.450 + /// <summary>
14.451 + /// Retrieves the number of Input reports the HID driver will store.
14.452 + /// </summary>
14.453 + ///
14.454 + /// <param name="hidDeviceObject"> a handle to a device </param>
14.455 + /// <param name="numberOfInputBuffers"> an integer to hold the returned value. </param>
14.456 + ///
14.457 + /// <returns>
14.458 + /// True on success, False on failure.
14.459 + /// </returns>
14.460 +
14.461 + internal Boolean GetNumberOfInputBuffers(SafeFileHandle hidDeviceObject, ref Int32 numberOfInputBuffers)
14.462 + {
14.463 + try
14.464 + {
14.465 + // ***
14.466 + // API function: HidD_GetNumInputBuffers
14.467 +
14.468 + // Purpose: retrieves the number of Input reports the host can store.
14.469 + // Not supported by Windows 98 Gold.
14.470 + // If the buffer is full and another report arrives, the host drops the
14.471 + // ldest report.
14.472 +
14.473 + // Accepts: a handle to a device and an integer to hold the number of buffers.
14.474 +
14.475 + // Returns: True on success, False on failure.
14.476 + // ***
14.477 +
14.478 + Boolean success = NativeMethods.HidD_GetNumInputBuffers(hidDeviceObject, ref numberOfInputBuffers);
14.479 +
14.480 + return success;
14.481 + }
14.482 +
14.483 + catch (Exception ex)
14.484 + {
14.485 + DisplayException(ModuleName, ex);
14.486 + throw;
14.487 + }
14.488 + }
14.489 +
14.490 + /// <summary>
14.491 + /// Timeout if read or write via interrupt transfer doesn't return.
14.492 + /// </summary>
14.493 +
14.494 + internal void OnTimeout()
14.495 + {
14.496 + try
14.497 + {
14.498 + // No action required.
14.499 +
14.500 + Debug.Print("timeout");
14.501 + }
14.502 + catch (Exception ex)
14.503 + {
14.504 + DisplayException(ModuleName, ex);
14.505 + throw;
14.506 + }
14.507 + }
14.508 +
14.509 + /// <summary>
14.510 + /// Attempts to open a handle to a HID.
14.511 + /// </summary>
14.512 + /// <param name="devicePathName"> device path name returned by SetupDiGetDeviceInterfaceDetail </param>
14.513 + /// <param name="readAndWrite"> true if requesting read/write access for Input and Output reports </param>
14.514 + /// <returns> hidHandle - a handle to the HID </returns>
14.515 +
14.516 + internal SafeFileHandle OpenHandle(String devicePathName, Boolean readAndWrite)
14.517 + {
14.518 + SafeFileHandle hidHandle;
14.519 +
14.520 + try
14.521 + {
14.522 + if (readAndWrite)
14.523 + {
14.524 + // ***
14.525 + // API function:
14.526 + // CreateFile
14.527 +
14.528 + // Purpose:
14.529 + // Retrieves a handle to a device.
14.530 +
14.531 + // Accepts:
14.532 + // A device path name returned by SetupDiGetDeviceInterfaceDetail
14.533 + // The type of access requested (read/write).
14.534 + // FILE_SHARE attributes to allow other processes to access the device while this handle is open.
14.535 + // A Security structure or IntPtr.Zero.
14.536 + // A creation disposition value. Use OPEN_EXISTING for devices.
14.537 + // Flags and attributes for files. Not used for devices.
14.538 + // Handle to a template file. Not used.
14.539 +
14.540 + // Returns: a handle without read or write access.
14.541 + // This enables obtaining information about all HIDs, even system
14.542 + // keyboards and mice.
14.543 + // Separate handles are used for reading and writing.
14.544 + // ***
14.545 +
14.546 + hidHandle = FileIo.CreateFile(devicePathName, FileIo.GenericRead | FileIo.GenericWrite, FileIo.FileShareRead | FileIo.FileShareWrite, IntPtr.Zero, FileIo.OpenExisting, 0, IntPtr.Zero);
14.547 + }
14.548 + else
14.549 + {
14.550 + hidHandle = FileIo.CreateFile(devicePathName, 0, FileIo.FileShareRead | FileIo.FileShareWrite, IntPtr.Zero, FileIo.OpenExisting, 0, IntPtr.Zero);
14.551 + }
14.552 + }
14.553 +
14.554 + catch (Exception ex)
14.555 + {
14.556 + DisplayException(ModuleName, ex);
14.557 + throw;
14.558 + }
14.559 + return hidHandle;
14.560 + }
14.561 +
14.562 + /// <summary>
14.563 + /// Writes a Feature report to the device.
14.564 + /// </summary>
14.565 + ///
14.566 + /// <param name="outFeatureReportBuffer"> contains the report ID and report data. </param>
14.567 + /// <param name="hidHandle"> handle to the device. </param>
14.568 + ///
14.569 + /// <returns>
14.570 + /// True on success. False on failure.
14.571 + /// </returns>
14.572 +
14.573 + internal Boolean SendFeatureReport(SafeFileHandle hidHandle, Byte[] outFeatureReportBuffer)
14.574 + {
14.575 + try
14.576 + {
14.577 + // ***
14.578 + // API function: HidD_SetFeature
14.579 +
14.580 + // Purpose: Attempts to send a Feature report to the device.
14.581 +
14.582 + // Accepts:
14.583 + // A handle to a HID
14.584 + // A pointer to a buffer containing the report ID and report
14.585 + // The size of the buffer.
14.586 +
14.587 + // Returns: true on success, false on failure.
14.588 + // ***
14.589 +
14.590 + Boolean success = NativeMethods.HidD_SetFeature(hidHandle, outFeatureReportBuffer, outFeatureReportBuffer.Length);
14.591 +
14.592 + Debug.Print("HidD_SetFeature success = " + success);
14.593 +
14.594 + return success;
14.595 + }
14.596 +
14.597 + catch (Exception ex)
14.598 + {
14.599 + DisplayException(ModuleName, ex);
14.600 + throw;
14.601 + }
14.602 + }
14.603 +
14.604 + /// <summary>
14.605 + /// Writes an Output report to the device using a control transfer.
14.606 + /// </summary>
14.607 + ///
14.608 + /// <param name="outputReportBuffer"> contains the report ID and report data. </param>
14.609 + /// <param name="hidHandle"> handle to the device. </param>
14.610 + ///
14.611 + /// <returns>
14.612 + /// True on success. False on failure.
14.613 + /// </returns>
14.614 +
14.615 + internal Boolean SendOutputReportViaControlTransfer(SafeFileHandle hidHandle, Byte[] outputReportBuffer)
14.616 + {
14.617 + try
14.618 + {
14.619 + // ***
14.620 + // API function: HidD_SetOutputReport
14.621 +
14.622 + // Purpose:
14.623 + // Attempts to send an Output report to the device using a control transfer.
14.624 +
14.625 + // Accepts:
14.626 + // A handle to a HID
14.627 + // A pointer to a buffer containing the report ID and report
14.628 + // The size of the buffer.
14.629 +
14.630 + // Returns: true on success, false on failure.
14.631 + // ***
14.632 +
14.633 + Boolean success = NativeMethods.HidD_SetOutputReport(hidHandle, outputReportBuffer, outputReportBuffer.Length + 1);
14.634 +
14.635 + Debug.Print("HidD_SetOutputReport success = " + success);
14.636 +
14.637 + return success;
14.638 + }
14.639 +
14.640 + catch (Exception ex)
14.641 + {
14.642 + DisplayException(ModuleName, ex);
14.643 + throw;
14.644 + }
14.645 + }
14.646 +
14.647 + /// <summary>
14.648 + /// Writes an Output report to the device using an interrupt transfer.
14.649 + /// </summary>
14.650 + ///
14.651 + /// <param name="fileStreamDeviceData"> the Filestream for writing data. </param>
14.652 + /// <param name="hidHandle"> SafeFileHandle to the device. </param>
14.653 + /// <param name="outputReportBuffer"> contains the report ID and report data. </param>
14.654 + /// <param name="cts"> CancellationTokenSource </param>
14.655 + ///
14.656 + /// <returns>
14.657 + /// 1 on success. 0 on failure.
14.658 + /// </returns>
14.659 +
14.660 + internal async Task<Boolean> SendOutputReportViaInterruptTransfer
14.661 + (FileStream fileStreamDeviceData, SafeFileHandle hidHandle, Byte[] outputReportBuffer, CancellationTokenSource cts)
14.662 + {
14.663 + try
14.664 + {
14.665 + var success = false;
14.666 +
14.667 + // Begin writing the Output report.
14.668 +
14.669 + Task t = fileStreamDeviceData.WriteAsync(outputReportBuffer, 0, outputReportBuffer.Length, cts.Token);
14.670 +
14.671 + await t;
14.672 +
14.673 + // Gets to here only if the write operation completed before a timeout.
14.674 +
14.675 + Debug.Print("Asynchronous write completed");
14.676 +
14.677 + // The operation has one of these completion states:
14.678 +
14.679 + switch (t.Status)
14.680 + {
14.681 + case TaskStatus.RanToCompletion:
14.682 + success = true;
14.683 + Debug.Print("Output report written to device");
14.684 + break;
14.685 + case TaskStatus.Canceled:
14.686 + Debug.Print("Task canceled");
14.687 + break;
14.688 + case TaskStatus.Faulted:
14.689 + Debug.Print("Unhandled exception");
14.690 + break;
14.691 + }
14.692 +
14.693 + return success;
14.694 + }
14.695 + catch (Exception ex)
14.696 + {
14.697 + DisplayException(ModuleName, ex);
14.698 + throw;
14.699 + }
14.700 + }
14.701 +
14.702 + /// <summary>
14.703 + /// sets the number of input reports the host HID driver store.
14.704 + /// </summary>
14.705 + ///
14.706 + /// <param name="hidDeviceObject"> a handle to the device.</param>
14.707 + /// <param name="numberBuffers"> the requested number of input reports. </param>
14.708 + ///
14.709 + /// <returns>
14.710 + /// True on success. False on failure.
14.711 + /// </returns>
14.712 +
14.713 + internal Boolean SetNumberOfInputBuffers(SafeFileHandle hidDeviceObject, Int32 numberBuffers)
14.714 + {
14.715 + try
14.716 + {
14.717 + // ***
14.718 + // API function: HidD_SetNumInputBuffers
14.719 +
14.720 + // Purpose: Sets the number of Input reports the host can store.
14.721 + // If the buffer is full and another report arrives, the host drops the
14.722 + // oldest report.
14.723 +
14.724 + // Requires:
14.725 + // A handle to a HID
14.726 + // An integer to hold the number of buffers.
14.727 +
14.728 + // Returns: true on success, false on failure.
14.729 + // ***
14.730 +
14.731 + NativeMethods.HidD_SetNumInputBuffers(hidDeviceObject, numberBuffers);
14.732 + return true;
14.733 + }
14.734 +
14.735 + catch (Exception ex)
14.736 + {
14.737 + DisplayException(ModuleName, ex);
14.738 + throw;
14.739 + }
14.740 + }
14.741 + }
14.742 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/HidDeclarations.cs Wed May 14 07:52:21 2014 +0200
15.3 @@ -0,0 +1,135 @@
15.4 +using Microsoft.Win32.SafeHandles;
15.5 +using System;
15.6 +using System.Runtime.InteropServices;
15.7 +
15.8 +namespace GenericHid
15.9 +{
15.10 + /// <summary>
15.11 + /// API declarations for HID communications.
15.12 + /// </summary>
15.13 + internal sealed partial class Hid
15.14 + {
15.15 + internal static class NativeMethods
15.16 + {
15.17 + // from hidpi.h
15.18 + // Typedef enum defines a set of integer constants for HidP_Report_Type
15.19 +
15.20 + internal const Int16 HidP_Input = 0;
15.21 + internal const Int16 HidP_Output = 1;
15.22 + internal const Int16 HidP_Feature = 2;
15.23 +
15.24 + [StructLayout(LayoutKind.Sequential)]
15.25 + internal struct HIDD_ATTRIBUTES
15.26 + {
15.27 + internal Int32 Size;
15.28 + internal UInt16 VendorID;
15.29 + internal UInt16 ProductID;
15.30 + internal UInt16 VersionNumber;
15.31 + }
15.32 +
15.33 + internal struct HIDP_CAPS
15.34 + {
15.35 + internal Int16 Usage;
15.36 + internal Int16 UsagePage;
15.37 + internal Int16 InputReportByteLength;
15.38 + internal Int16 OutputReportByteLength;
15.39 + internal Int16 FeatureReportByteLength;
15.40 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] internal Int16[] Reserved;
15.41 + internal Int16 NumberLinkCollectionNodes;
15.42 + internal Int16 NumberInputButtonCaps;
15.43 + internal Int16 NumberInputValueCaps;
15.44 + internal Int16 NumberInputDataIndices;
15.45 + internal Int16 NumberOutputButtonCaps;
15.46 + internal Int16 NumberOutputValueCaps;
15.47 + internal Int16 NumberOutputDataIndices;
15.48 + internal Int16 NumberFeatureButtonCaps;
15.49 + internal Int16 NumberFeatureValueCaps;
15.50 + internal Int16 NumberFeatureDataIndices;
15.51 + }
15.52 +
15.53 + // If IsRange is false, UsageMin is the Usage and UsageMax is unused.
15.54 + // If IsStringRange is false, StringMin is the String index and StringMax is unused.
15.55 + // If IsDesignatorRange is false, DesignatorMin is the designator index and DesignatorMax is unused.
15.56 +
15.57 + internal struct HidP_Value_Caps
15.58 + {
15.59 + internal Int16 UsagePage;
15.60 + internal Byte ReportID;
15.61 + internal Int32 IsAlias;
15.62 + internal Int16 BitField;
15.63 + internal Int16 LinkCollection;
15.64 + internal Int16 LinkUsage;
15.65 + internal Int16 LinkUsagePage;
15.66 + internal Int32 IsRange;
15.67 + internal Int32 IsStringRange;
15.68 + internal Int32 IsDesignatorRange;
15.69 + internal Int32 IsAbsolute;
15.70 + internal Int32 HasNull;
15.71 + internal Byte Reserved;
15.72 + internal Int16 BitSize;
15.73 + internal Int16 ReportCount;
15.74 + internal Int16 Reserved2;
15.75 + internal Int16 Reserved3;
15.76 + internal Int16 Reserved4;
15.77 + internal Int16 Reserved5;
15.78 + internal Int16 Reserved6;
15.79 + internal Int32 LogicalMin;
15.80 + internal Int32 LogicalMax;
15.81 + internal Int32 PhysicalMin;
15.82 + internal Int32 PhysicalMax;
15.83 + internal Int16 UsageMin;
15.84 + internal Int16 UsageMax;
15.85 + internal Int16 StringMin;
15.86 + internal Int16 StringMax;
15.87 + internal Int16 DesignatorMin;
15.88 + internal Int16 DesignatorMax;
15.89 + internal Int16 DataIndexMin;
15.90 + internal Int16 DataIndexMax;
15.91 + }
15.92 +
15.93 + [DllImport("hid.dll", SetLastError = true)]
15.94 + internal static extern Boolean HidD_FlushQueue(SafeFileHandle HidDeviceObject);
15.95 +
15.96 + [DllImport("hid.dll", SetLastError = true)]
15.97 + internal static extern Boolean HidD_FreePreparsedData(IntPtr PreparsedData);
15.98 +
15.99 + [DllImport("hid.dll", SetLastError = true)]
15.100 + internal static extern Boolean HidD_GetAttributes(SafeFileHandle HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);
15.101 +
15.102 + [DllImport("hid.dll", SetLastError = true)]
15.103 + internal static extern Boolean HidD_GetFeature(SafeFileHandle HidDeviceObject, Byte[] lpReportBuffer,
15.104 + Int32 ReportBufferLength);
15.105 +
15.106 + [DllImport("hid.dll", SetLastError = true)]
15.107 + internal static extern Boolean HidD_GetInputReport(SafeFileHandle HidDeviceObject, Byte[] lpReportBuffer,
15.108 + Int32 ReportBufferLength);
15.109 +
15.110 + [DllImport("hid.dll", SetLastError = true)]
15.111 + internal static extern void HidD_GetHidGuid(ref Guid HidGuid);
15.112 +
15.113 + [DllImport("hid.dll", SetLastError = true)]
15.114 + internal static extern Boolean HidD_GetNumInputBuffers(SafeFileHandle HidDeviceObject, ref Int32 NumberBuffers);
15.115 +
15.116 + [DllImport("hid.dll", SetLastError = true)]
15.117 + internal static extern Boolean HidD_GetPreparsedData(SafeFileHandle HidDeviceObject, ref IntPtr PreparsedData);
15.118 +
15.119 + [DllImport("hid.dll", SetLastError = true)]
15.120 + internal static extern Boolean HidD_SetFeature(SafeFileHandle HidDeviceObject, Byte[] lpReportBuffer,
15.121 + Int32 ReportBufferLength);
15.122 +
15.123 + [DllImport("hid.dll", SetLastError = true)]
15.124 + internal static extern Boolean HidD_SetNumInputBuffers(SafeFileHandle HidDeviceObject, Int32 NumberBuffers);
15.125 +
15.126 + [DllImport("hid.dll", SetLastError = true)]
15.127 + internal static extern Boolean HidD_SetOutputReport(SafeFileHandle HidDeviceObject, Byte[] lpReportBuffer,
15.128 + Int32 ReportBufferLength);
15.129 +
15.130 + [DllImport("hid.dll", SetLastError = true)]
15.131 + internal static extern Int32 HidP_GetCaps(IntPtr PreparsedData, ref HIDP_CAPS Capabilities);
15.132 +
15.133 + [DllImport("hid.dll", SetLastError = true)]
15.134 + internal static extern Int32 HidP_GetValueCaps(Int32 ReportType, Byte[] ValueCaps, ref Int32 ValueCapsLength,
15.135 + IntPtr PreparsedData);
15.136 + }
15.137 + }
15.138 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/Properties/Resources.Designer.cs Wed May 14 07:52:21 2014 +0200
16.3 @@ -0,0 +1,63 @@
16.4 +//------------------------------------------------------------------------------
16.5 +// <auto-generated>
16.6 +// This code was generated by a tool.
16.7 +// Runtime Version:4.0.30319.18010
16.8 +//
16.9 +// Changes to this file may cause incorrect behavior and will be lost if
16.10 +// the code is regenerated.
16.11 +// </auto-generated>
16.12 +//------------------------------------------------------------------------------
16.13 +
16.14 +namespace GenericHid.Properties {
16.15 + using System;
16.16 +
16.17 +
16.18 + /// <summary>
16.19 + /// A strongly-typed resource class, for looking up localized strings, etc.
16.20 + /// </summary>
16.21 + // This class was auto-generated by the StronglyTypedResourceBuilder
16.22 + // class via a tool like ResGen or Visual Studio.
16.23 + // To add or remove a member, edit your .ResX file then rerun ResGen
16.24 + // with the /str option, or rebuild your VS project.
16.25 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
16.26 + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
16.27 + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16.28 + internal class Resources {
16.29 +
16.30 + private static global::System.Resources.ResourceManager resourceMan;
16.31 +
16.32 + private static global::System.Globalization.CultureInfo resourceCulture;
16.33 +
16.34 + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
16.35 + internal Resources() {
16.36 + }
16.37 +
16.38 + /// <summary>
16.39 + /// Returns the cached ResourceManager instance used by this class.
16.40 + /// </summary>
16.41 + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
16.42 + internal static global::System.Resources.ResourceManager ResourceManager {
16.43 + get {
16.44 + if (object.ReferenceEquals(resourceMan, null)) {
16.45 + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GenericHid.Properties.Resources", typeof(Resources).Assembly);
16.46 + resourceMan = temp;
16.47 + }
16.48 + return resourceMan;
16.49 + }
16.50 + }
16.51 +
16.52 + /// <summary>
16.53 + /// Overrides the current thread's CurrentUICulture property for all
16.54 + /// resource lookups using this strongly typed resource class.
16.55 + /// </summary>
16.56 + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
16.57 + internal static global::System.Globalization.CultureInfo Culture {
16.58 + get {
16.59 + return resourceCulture;
16.60 + }
16.61 + set {
16.62 + resourceCulture = value;
16.63 + }
16.64 + }
16.65 + }
16.66 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/Properties/Resources.resx Wed May 14 07:52:21 2014 +0200
17.3 @@ -0,0 +1,110 @@
17.4 +<?xml version="1.0" encoding="utf-8"?>
17.5 +<root>
17.6 + <!--
17.7 + Microsoft ResX Schema
17.8 +
17.9 + Version 2.0
17.10 +
17.11 + The primary goals of this format is to allow a simple XML format
17.12 + that is mostly human readable. The generation and parsing of the
17.13 + various data types are done through the TypeConverter classes
17.14 + associated with the data types.
17.15 +
17.16 + Example:
17.17 +
17.18 + ... ado.net/XML headers & schema ...
17.19 + <resheader name="resmimetype">text/microsoft-resx</resheader>
17.20 + <resheader name="version">2.0</resheader>
17.21 + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
17.22 + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
17.23 + <data name="Name1">this is my long string</data>
17.24 + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
17.25 + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
17.26 + [base64 mime encoded serialized .NET Framework object]
17.27 + </data>
17.28 + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
17.29 + [base64 mime encoded string representing a byte array form of the .NET Framework object]
17.30 + </data>
17.31 +
17.32 + There are any number of "resheader" rows that contain simple
17.33 + name/value pairs.
17.34 +
17.35 + Each data row contains a name, and value. The row also contains a
17.36 + type or mimetype. Type corresponds to a .NET class that support
17.37 + text/value conversion through the TypeConverter architecture.
17.38 + Classes that don't support this are serialized and stored with the
17.39 + mimetype set.
17.40 +
17.41 + The mimetype is used for serialized objects, and tells the
17.42 + ResXResourceReader how to depersist the object. This is currently not
17.43 + extensible. For a given mimetype the value must be set accordingly:
17.44 +
17.45 + Note - application/x-microsoft.net.object.binary.base64 is the format
17.46 + that the ResXResourceWriter will generate, however the reader can
17.47 + read any of the formats listed below.
17.48 +
17.49 + mimetype: application/x-microsoft.net.object.binary.base64
17.50 + value : The object must be serialized with
17.51 + : System.Serialization.Formatters.Binary.BinaryFormatter
17.52 + : and then encoded with base64 encoding.
17.53 +
17.54 + mimetype: application/x-microsoft.net.object.soap.base64
17.55 + value : The object must be serialized with
17.56 + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
17.57 + : and then encoded with base64 encoding.
17.58 +
17.59 + mimetype: application/x-microsoft.net.object.bytearray.base64
17.60 + value : The object must be serialized into a byte array
17.61 + : using a System.ComponentModel.TypeConverter
17.62 + : and then encoded with base64 encoding.
17.63 + -->
17.64 + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
17.65 + <xsd:element name="root" msdata:IsDataSet="true">
17.66 + <xsd:complexType>
17.67 + <xsd:choice maxOccurs="unbounded">
17.68 + <xsd:element name="metadata">
17.69 + <xsd:complexType>
17.70 + <xsd:sequence>
17.71 + <xsd:element name="value" type="xsd:string" minOccurs="0" />
17.72 + </xsd:sequence>
17.73 + <xsd:attribute name="name" type="xsd:string" />
17.74 + <xsd:attribute name="type" type="xsd:string" />
17.75 + <xsd:attribute name="mimetype" type="xsd:string" />
17.76 + </xsd:complexType>
17.77 + </xsd:element>
17.78 + <xsd:element name="data">
17.79 + <xsd:complexType>
17.80 + <xsd:sequence>
17.81 + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
17.82 + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
17.83 + </xsd:sequence>
17.84 + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
17.85 + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
17.86 + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
17.87 + </xsd:complexType>
17.88 + </xsd:element>
17.89 + <xsd:element name="resheader">
17.90 + <xsd:complexType>
17.91 + <xsd:sequence>
17.92 + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
17.93 + </xsd:sequence>
17.94 + <xsd:attribute name="name" type="xsd:string" use="required" />
17.95 + </xsd:complexType>
17.96 + </xsd:element>
17.97 + </xsd:choice>
17.98 + </xsd:complexType>
17.99 + </xsd:element>
17.100 + </xsd:schema>
17.101 + <resheader name="resmimetype">
17.102 + <value>text/microsoft-resx</value>
17.103 + </resheader>
17.104 + <resheader name="version">
17.105 + <value>2.0</value>
17.106 + </resheader>
17.107 + <resheader name="reader">
17.108 + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
17.109 + </resheader>
17.110 + <resheader name="writer">
17.111 + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
17.112 + </resheader>
17.113 +</root>
17.114 \ No newline at end of file
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/Properties/Settings.Designer.cs Wed May 14 07:52:21 2014 +0200
18.3 @@ -0,0 +1,26 @@
18.4 +//------------------------------------------------------------------------------
18.5 +// <auto-generated>
18.6 +// This code was generated by a tool.
18.7 +// Runtime Version:4.0.30319.18010
18.8 +//
18.9 +// Changes to this file may cause incorrect behavior and will be lost if
18.10 +// the code is regenerated.
18.11 +// </auto-generated>
18.12 +//------------------------------------------------------------------------------
18.13 +
18.14 +namespace GenericHid.Properties {
18.15 +
18.16 +
18.17 + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
18.18 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
18.19 + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
18.20 +
18.21 + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
18.22 +
18.23 + public static Settings Default {
18.24 + get {
18.25 + return defaultInstance;
18.26 + }
18.27 + }
18.28 + }
18.29 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/Properties/Settings.settings Wed May 14 07:52:21 2014 +0200
19.3 @@ -0,0 +1,6 @@
19.4 +<?xml version='1.0' encoding='utf-8'?>
19.5 +<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
19.6 + <Profiles>
19.7 + <Profile Name="(Default)" />
19.8 + </Profiles>
19.9 +</SettingsFile>
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/app.config Wed May 14 07:52:21 2014 +0200
20.3 @@ -0,0 +1,3 @@
20.4 +<?xml version="1.0"?>
20.5 +<configuration>
20.6 +<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/publish/GenericHid.application Wed May 14 07:52:21 2014 +0200
21.3 @@ -0,0 +1,21 @@
21.4 +<?xml version="1.0" encoding="utf-8"?>
21.5 +<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
21.6 + <assemblyIdentity name="GenericHid.application" version="6.2.0.0" publicKeyToken="e912df4371957e61" language="neutral" processorArchitecture="msil" xmlns="urn:schemas-microsoft-com:asm.v1" />
21.7 + <description asmv2:publisher="GenericHid" asmv2:product="GenericHid" xmlns="urn:schemas-microsoft-com:asm.v1" />
21.8 + <deployment install="true" mapFileExtensions="true" />
21.9 + <compatibleFrameworks xmlns="urn:schemas-microsoft-com:clickonce.v2">
21.10 + <framework targetVersion="4.5" profile="Full" supportedRuntime="4.0.30319" />
21.11 + </compatibleFrameworks>
21.12 + <dependency>
21.13 + <dependentAssembly dependencyType="install" codebase="Application Files\GenericHid_6_2_0_0\GenericHid.exe.manifest" size="7558">
21.14 + <assemblyIdentity name="GenericHid.exe" version="6.2.0.0" publicKeyToken="e912df4371957e61" language="neutral" processorArchitecture="msil" type="win32" />
21.15 + <hash>
21.16 + <dsig:Transforms>
21.17 + <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
21.18 + </dsig:Transforms>
21.19 + <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
21.20 + <dsig:DigestValue>oQgb8A8n+lzj+3t+OgYSWwxoRg2BjZwoA6qP23iuoq0=</dsig:DigestValue>
21.21 + </hash>
21.22 + </dependentAssembly>
21.23 + </dependency>
21.24 +<publisherIdentity name="CN=LVR2012\jan" issuerKeyHash="70f83b2370f422d4e3355b5c66f809cda26371c5" /><Signature Id="StrongNameSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>Lq11Sw3U1N8vRticxZzSjoQ6oqyNni1fUjnATzMnmvE=</DigestValue></Reference></SignedInfo><SignatureValue>RaX+F7wItRwo1xWOj5oNucSLJAEG+ZMa+gP92gUY2DeHBZJ3xl+8UYF/kuuSOf4DBNquvXRHyLXeegzkFttrqtO704gxqcIbXBcZi7w0PXZNmw+kN/8ykkWCShQiz8f3IYjqjQV199fxw3NAciCpWCLNSAMRYtVX6VyIEQCI6ns=</SignatureValue><KeyInfo Id="StrongNameKeyInfo"><KeyValue><RSAKeyValue><Modulus>vZK+hjF855eH6ywa/BZBvxkMJFFIIFjX0riqpVp0M088+99Ygevu3AGL1ajEdjQwry8w4ZXnz4jUfHSC2nhBKONyLrzV2dQH+RwonfAW8ExhueAb7u/pG77yb3T+kRbiHNPuRP8nlFTzm+riq/k1A1EqAK2n6MeVFUyk85S3xtU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><msrel:RelData xmlns:msrel="http://schemas.microsoft.com/windows/rel/2005/reldata"><r:license xmlns:r="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:as="http://schemas.microsoft.com/windows/pki/2005/Authenticode"><r:grant><as:ManifestInformation Hash="f19a27334fc039525f2d9e8daca23a848ed29cc59cd8462fdfd4d40d4b75ad2e" Description="" Url=""><as:assemblyIdentity name="GenericHid.application" version="6.2.0.0" publicKeyToken="e912df4371957e61" language="neutral" processorArchitecture="msil" xmlns="urn:schemas-microsoft-com:asm.v1" /></as:ManifestInformation><as:SignedBy /><as:AuthenticodePublisher><as:X509SubjectName>CN=LVR2012\jan</as:X509SubjectName></as:AuthenticodePublisher></r:grant><r:issuer><Signature Id="AuthenticodeSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" /><DigestValue>Nr/7DS53yGSNQxZA8cHgQphhjotTpOqFPw/G1Vh1qZI=</DigestValue></Reference></SignedInfo><SignatureValue>VEtiDTr4D9sGpmtS0wEej0Kmlx+zXyxZglD+CUVKbqW6YbPgfVbgZTRPtps+asBMqCusZUVUqtnwIvFJ89GwlKr+59nMUMlxiPuHFrnM8LJqWTMT05lJFO9P1h3t2U0pkCkbD+tFIpcLUxuVJmG+Lx9SH+nYnxY90QbhgAR43eg=</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>vZK+hjF855eH6ywa/BZBvxkMJFFIIFjX0riqpVp0M088+99Ygevu3AGL1ajEdjQwry8w4ZXnz4jUfHSC2nhBKONyLrzV2dQH+RwonfAW8ExhueAb7u/pG77yb3T+kRbiHNPuRP8nlFTzm+riq/k1A1EqAK2n6MeVFUyk85S3xtU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue><X509Data><X509Certificate>MIIBxTCCAS6gAwIBAgIQG1z/tZx30LZKDzrL/KUXPjANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDHhYATABWAFIAMgAwADEAMgBcAGoAYQBuMB4XDTEzMTAzMDAxMzYxNloXDTE0MTAzMDA3MzYxNlowITEfMB0GA1UEAx4WAEwAVgBSADIAMAAxADIAXABqAGEAbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvZK+hjF855eH6ywa/BZBvxkMJFFIIFjX0riqpVp0M088+99Ygevu3AGL1ajEdjQwry8w4ZXnz4jUfHSC2nhBKONyLrzV2dQH+RwonfAW8ExhueAb7u/pG77yb3T+kRbiHNPuRP8nlFTzm+riq/k1A1EqAK2n6MeVFUyk85S3xtUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQB5WjMIunQoSYZTqVnK1+emQt2+v/SzZc1oYY1G5ikE/t92Phyu0E9PgA6nXavF2IMrzOnmnNasTO9ygFQ+ck96TyD1FsQW9XRYxYdCn5oC+Caelwm5CPHRI2PKnw15IRDT9hHFj4AxYMSnN7uPXO+7eOjAbtRnynn0KAq+1PsFAA==</X509Certificate></X509Data></KeyInfo></Signature></r:issuer></r:license></msrel:RelData></KeyInfo></Signature></asmv1:assembly>
21.25 \ No newline at end of file
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/readme.txt Wed May 14 07:52:21 2014 +0200
22.3 @@ -0,0 +1,136 @@
22.4 + ///<summary>
22.5 + /// Project: GenericHid
22.6 + ///
22.7 + /// ***********************************************************************
22.8 + /// Software License Agreement
22.9 + ///
22.10 + /// Licensor grants any person obtaining a copy of this software ("You")
22.11 + /// a worldwide, royalty-free, non-exclusive license, for the duration of
22.12 + /// the copyright, free of charge, to store and execute the Software in a
22.13 + /// computer system and to incorporate the Software or any portion of it
22.14 + /// in computer programs You write.
22.15 + ///
22.16 + /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22.17 + /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22.18 + /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22.19 + /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22.20 + /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22.21 + /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22.22 + /// THE SOFTWARE.
22.23 + /// ***********************************************************************
22.24 + ///
22.25 + /// Author
22.26 + /// Jan Axelson
22.27 + ///
22.28 + /// This software was written using Visual Studio Express 2012 for Windows
22.29 + /// Desktop building for the .NET Framework v4.5.
22.30 + ///
22.31 + /// Purpose:
22.32 + /// Demonstrates USB communications with a generic HID-class device
22.33 + ///
22.34 + /// Requirements:
22.35 + /// Windows Vista or later and an attached USB generic Human Interface Device (HID).
22.36 + /// (Does not run on Windows XP or earlier because .NET Framework 4.5 will not install on these OSes.)
22.37 + ///
22.38 + /// Description:
22.39 + /// Finds an attached device that matches the vendor and product IDs in the form's
22.40 + /// text boxes.
22.41 + ///
22.42 + /// Retrieves the device's capabilities.
22.43 + /// Sends and requests HID reports.
22.44 + ///
22.45 + /// Uses the System.Management class and Windows Management Instrumentation (WMI) to detect
22.46 + /// when a device is attached or removed.
22.47 + ///
22.48 + /// A list box displays the data sent and received along with error and status messages.
22.49 + /// You can select data to send and 1-time or periodic transfers.
22.50 + ///
22.51 + /// You can change the size of the host's Input report buffer and request to use control
22.52 + /// transfers only to exchange Input and Output reports.
22.53 + ///
22.54 + /// To view additional debugging messages, in the Visual Studio development environment,
22.55 + /// from the main menu, select Build > Configuration Manager > Active Solution Configuration
22.56 + /// and select Configuration > Debug and from the main menu, select View > Output.
22.57 + ///
22.58 + /// The application uses asynchronous FileStreams to read Input reports and write Output
22.59 + /// reports so the application's main thread doesn't have to wait for the device to retrieve a
22.60 + /// report when the HID driver's buffer is empty or send a report when the device's endpoint is busy.
22.61 + ///
22.62 + /// For code that finds a device and opens handles to it, see the FindTheHid routine in frmMain.cs.
22.63 + /// For code that reads from the device, see GetInputReportViaInterruptTransfer,
22.64 + /// GetInputReportViaControlTransfer, and GetFeatureReport in Hid.cs.
22.65 + /// For code that writes to the device, see SendInputReportViaInterruptTransfer,
22.66 + /// SendInputReportViaControlTransfer, and SendFeatureReport in Hid.cs.
22.67 + ///
22.68 + /// This project includes the following modules:
22.69 + ///
22.70 + /// GenericHid.cs - runs the application.
22.71 + /// FrmMain.cs - routines specific to the form.
22.72 + /// Hid.cs - routines specific to HID communications.
22.73 + /// DeviceManagement.cs - routine for obtaining a handle to a device from its GUID.
22.74 + /// Debugging.cs - contains a routine for displaying API error messages.
22.75 + /// HidDeclarations.cs - Declarations for API functions used by Hid.cs.
22.76 + /// FileIODeclarations.cs - Declarations for file-related API functions.
22.77 + /// DeviceManagementDeclarations.cs - Declarations for API functions used by DeviceManagement.cs.
22.78 + /// DebuggingDeclarations.cs - Declarations for API functions used by Debugging.cs.
22.79 + ///
22.80 + /// Companion device firmware for several device CPUs is available from www.Lvr.com/hidpage.htm
22.81 + /// You can use any generic HID (not a system mouse or keyboard) that sends and receives reports.
22.82 + /// This application will not detect or communicate with non-HID-class devices.
22.83 + ///
22.84 + /// For more information about HIDs and USB, and additional example device firmware to use
22.85 + /// with this application, visit Lakeview Research at http://Lvr.com
22.86 + /// Send comments, bug reports, etc. to jan@Lvr.com or post on my PORTS forum: http://www.lvr.com/forum
22.87 + ///
22.88 + /// V6.2
22.89 + /// 11/12/13
22.90 + /// Disabled form buttons when a transfer is in progress.
22.91 + /// Other minor edits for clarity and readability.
22.92 + /// Will NOT run on Windows XP or earlier, see below.
22.93 + ///
22.94 + /// V6.1
22.95 + /// 10/28/13
22.96 + /// Uses the .NET System.Management class to detect device arrival and removal with WMI instead of Win32 RegisterDeviceNotification.
22.97 + /// Other minor edits.
22.98 + /// Will NOT run on Windows XP or earlier, see below.
22.99 + ///
22.100 + /// V6.0
22.101 + /// 2/8/13
22.102 + /// This version will NOT run on Windows XP or earlier because the code uses .NET Framework 4.5 to support asynchronous FileStreams.
22.103 + /// The .NET Framework 4.5 redistributable is compatible with Windows 8, Windows 7 SP1, Windows Server 2008 R2 SP1,
22.104 + /// Windows Server 2008 SP2, Windows Vista SP2, and Windows Vista SP3.
22.105 + /// For compatibility, replaced ToInt32 with ToInt64 here:
22.106 + /// IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
22.107 + /// and here:
22.108 + /// if ((deviceNotificationHandle.ToInt64() == IntPtr.Zero.ToInt64()))
22.109 + /// For compatibility if the charset isn't English, added System.Globalization.CultureInfo.InvariantCulture here:
22.110 + /// if ((String.Compare(DeviceNameString, mydevicePathName, true, System.Globalization.CultureInfo.InvariantCulture) == 0))
22.111 + /// Replaced all Microsoft.VisualBasic namespace code with other .NET equivalents.
22.112 + /// Revised user interface for more flexibility.
22.113 + /// Moved interrupt-transfer and other HID-specific code to Hid.cs.
22.114 + /// Used JetBrains ReSharper to clean up the code: http://www.jetbrains.com/resharper/
22.115 + ///
22.116 + /// V5.0
22.117 + /// 3/30/11
22.118 + /// Replaced ReadFile and WriteFile with FileStreams. Thanks to Joe Dunne and John on my Ports forum for tips on this.
22.119 + /// Simplified Hid.cs.
22.120 + /// Replaced the form timer with a system timer.
22.121 + ///
22.122 + /// V4.6
22.123 + /// 1/12/10
22.124 + /// Supports Vendor IDs and Product IDs up to FFFFh.
22.125 + ///
22.126 + /// V4.52
22.127 + /// 11/10/09
22.128 + /// Changed HIDD_ATTRIBUTES to use UInt16
22.129 + ///
22.130 + /// V4.51
22.131 + /// 2/11/09
22.132 + /// Moved Free_ and similar to Finally blocks to ensure they execute.
22.133 + ///
22.134 + /// V4.5
22.135 + /// 2/9/09
22.136 + /// Changes to support 64-bit systems, memory management, and other corrections.
22.137 + /// Big thanks to Peter Nielsen.
22.138 + ///
22.139 + /// </summary>