FrmMain.cs
author sl
Wed, 14 May 2014 16:37:44 +0200
changeset 4 0220435cf48a
parent 3 f5e6a5b8a56a
child 5 8ea7a7e29c4d
permissions -rw-r--r--
Newly added device are now showing green. Removed devices are showing red.
Other devices are showing black. Devices in unknown state are showing purple.
sl@0
     1
using Microsoft.Win32.SafeHandles;
sl@0
     2
using System;
sl@0
     3
using System.Diagnostics;
sl@0
     4
using System.Globalization;
sl@0
     5
using System.IO;
sl@0
     6
using System.Management;
sl@0
     7
using System.Runtime.InteropServices;
sl@0
     8
using System.Threading;
sl@0
     9
using System.Timers;
sl@0
    10
using System.Windows.Forms;
sl@3
    11
using System.Collections.Generic;
sl@3
    12
using System.Drawing;
sl@0
    13
sl@0
    14
namespace GenericHid
sl@0
    15
{
sl@0
    16
	///<summary>
sl@0
    17
	/// Project: GenericHid
sl@2
    18
	///
sl@0
    19
	/// ***********************************************************************
sl@0
    20
	/// Software License Agreement
sl@0
    21
	///
sl@2
    22
	/// Licensor grants any person obtaining a copy of this software ("You")
sl@2
    23
	/// a worldwide, royalty-free, non-exclusive license, for the duration of
sl@2
    24
	/// the copyright, free of charge, to store and execute the Software in a
sl@2
    25
	/// computer system and to incorporate the Software or any portion of it
sl@2
    26
	/// in computer programs You write.
sl@2
    27
	///
sl@0
    28
	/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
sl@0
    29
	/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
sl@0
    30
	/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
sl@0
    31
	/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
sl@0
    32
	/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
sl@0
    33
	/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
sl@0
    34
	/// THE SOFTWARE.
sl@0
    35
	/// ***********************************************************************
sl@2
    36
	///
sl@2
    37
	/// Author
sl@2
    38
	/// Jan Axelson
sl@2
    39
	///
sl@0
    40
	/// This software was written using Visual Studio Express 2012 for Windows
sl@0
    41
	/// Desktop building for the .NET Framework v4.5.
sl@2
    42
	///
sl@2
    43
	/// Purpose:
sl@0
    44
	/// Demonstrates USB communications with a generic HID-class device
sl@2
    45
	///
sl@0
    46
	/// Requirements:
sl@0
    47
	/// Windows Vista or later and an attached USB generic Human Interface Device (HID).
sl@2
    48
	/// (Does not run on Windows XP or earlier because .NET Framework 4.5 will not install on these OSes.)
sl@2
    49
	///
sl@0
    50
	/// Description:
sl@2
    51
	/// Finds an attached device that matches the vendor and product IDs in the form's
sl@0
    52
	/// text boxes.
sl@2
    53
	///
sl@0
    54
	/// Retrieves the device's capabilities.
sl@0
    55
	/// Sends and requests HID reports.
sl@2
    56
	///
sl@2
    57
	/// Uses the System.Management class and Windows Management Instrumentation (WMI) to detect
sl@0
    58
	/// when a device is attached or removed.
sl@2
    59
	///
sl@0
    60
	/// A list box displays the data sent and received along with error and status messages.
sl@0
    61
	/// You can select data to send and 1-time or periodic transfers.
sl@2
    62
	///
sl@0
    63
	/// You can change the size of the host's Input report buffer and request to use control
sl@0
    64
	/// transfers only to exchange Input and Output reports.
sl@2
    65
	///
sl@0
    66
	/// To view additional debugging messages, in the Visual Studio development environment,
sl@2
    67
	/// from the main menu, select Build > Configuration Manager > Active Solution Configuration
sl@0
    68
	/// and select Configuration > Debug and from the main menu, select View > Output.
sl@2
    69
	///
sl@2
    70
	/// The application uses asynchronous FileStreams to read Input reports and write Output
sl@2
    71
	/// reports so the application's main thread doesn't have to wait for the device to retrieve a
sl@2
    72
	/// report when the HID driver's buffer is empty or send a report when the device's endpoint is busy.
sl@2
    73
	///
sl@0
    74
	/// For code that finds a device and opens handles to it, see the FindTheHid routine in frmMain.cs.
sl@2
    75
	/// For code that reads from the device, see GetInputReportViaInterruptTransfer,
sl@0
    76
	/// GetInputReportViaControlTransfer, and GetFeatureReport in Hid.cs.
sl@2
    77
	/// For code that writes to the device, see SendInputReportViaInterruptTransfer,
sl@0
    78
	/// SendInputReportViaControlTransfer, and SendFeatureReport in Hid.cs.
sl@2
    79
	///
sl@0
    80
	/// This project includes the following modules:
sl@2
    81
	///
sl@0
    82
	/// GenericHid.cs - runs the application.
sl@0
    83
	/// FrmMain.cs - routines specific to the form.
sl@0
    84
	/// Hid.cs - routines specific to HID communications.
sl@0
    85
	/// DeviceManagement.cs - routine for obtaining a handle to a device from its GUID.
sl@0
    86
	/// Debugging.cs - contains a routine for displaying API error messages.
sl@0
    87
	/// HidDeclarations.cs - Declarations for API functions used by Hid.cs.
sl@0
    88
	/// FileIODeclarations.cs - Declarations for file-related API functions.
sl@0
    89
	/// DeviceManagementDeclarations.cs - Declarations for API functions used by DeviceManagement.cs.
sl@0
    90
	/// DebuggingDeclarations.cs - Declarations for API functions used by Debugging.cs.
sl@2
    91
	///
sl@0
    92
	/// Companion device firmware for several device CPUs is available from www.Lvr.com/hidpage.htm
sl@0
    93
	/// You can use any generic HID (not a system mouse or keyboard) that sends and receives reports.
sl@0
    94
	/// This application will not detect or communicate with non-HID-class devices.
sl@2
    95
	///
sl@0
    96
	/// For more information about HIDs and USB, and additional example device firmware to use
sl@2
    97
	/// with this application, visit Lakeview Research at http://Lvr.com
sl@2
    98
	/// Send comments, bug reports, etc. to jan@Lvr.com or post on my PORTS forum: http://www.lvr.com/forum
sl@2
    99
	///
sl@0
   100
	/// V6.2
sl@0
   101
	/// 11/12/13
sl@0
   102
	/// Disabled form buttons when a transfer is in progress.
sl@0
   103
	/// Other minor edits for clarity and readability.
sl@0
   104
	/// Will NOT run on Windows XP or earlier, see below.
sl@2
   105
	///
sl@0
   106
	/// V6.1
sl@0
   107
	/// 10/28/13
sl@0
   108
	/// Uses the .NET System.Management class to detect device arrival and removal with WMI instead of Win32 RegisterDeviceNotification.
sl@0
   109
	/// Other minor edits.
sl@0
   110
	/// Will NOT run on Windows XP or earlier, see below.
sl@2
   111
	///
sl@0
   112
	/// V6.0
sl@0
   113
	/// 2/8/13
sl@0
   114
	/// This version will NOT run on Windows XP or earlier because the code uses .NET Framework 4.5 to support asynchronous FileStreams.
sl@2
   115
	/// The .NET Framework 4.5 redistributable is compatible with Windows 8, Windows 7 SP1, Windows Server 2008 R2 SP1,
sl@0
   116
	/// Windows Server 2008 SP2, Windows Vista SP2, and Windows Vista SP3.
sl@0
   117
	/// For compatibility, replaced ToInt32 with ToInt64 here:
sl@0
   118
	/// IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
sl@0
   119
	/// and here:
sl@0
   120
	/// if ((deviceNotificationHandle.ToInt64() == IntPtr.Zero.ToInt64()))
sl@0
   121
	/// For compatibility if the charset isn't English, added System.Globalization.CultureInfo.InvariantCulture here:
sl@0
   122
	/// if ((String.Compare(DeviceNameString, mydevicePathName, true, System.Globalization.CultureInfo.InvariantCulture) == 0))
sl@0
   123
	/// Replaced all Microsoft.VisualBasic namespace code with other .NET equivalents.
sl@0
   124
	/// Revised user interface for more flexibility.
sl@0
   125
	/// Moved interrupt-transfer and other HID-specific code to Hid.cs.
sl@0
   126
	/// Used JetBrains ReSharper to clean up the code: http://www.jetbrains.com/resharper/
sl@2
   127
	///
sl@0
   128
	/// V5.0
sl@0
   129
	/// 3/30/11
sl@0
   130
	/// Replaced ReadFile and WriteFile with FileStreams. Thanks to Joe Dunne and John on my Ports forum for tips on this.
sl@0
   131
	/// Simplified Hid.cs.
sl@0
   132
	/// Replaced the form timer with a system timer.
sl@2
   133
	///
sl@0
   134
	/// V4.6
sl@0
   135
	/// 1/12/10
sl@0
   136
	/// Supports Vendor IDs and Product IDs up to FFFFh.
sl@0
   137
	///
sl@0
   138
	/// V4.52
sl@0
   139
	/// 11/10/09
sl@0
   140
	/// Changed HIDD_ATTRIBUTES to use UInt16
sl@2
   141
	///
sl@0
   142
	/// V4.51
sl@0
   143
	/// 2/11/09
sl@0
   144
	/// Moved Free_ and similar to Finally blocks to ensure they execute.
sl@2
   145
	///
sl@0
   146
	/// V4.5
sl@0
   147
	/// 2/9/09
sl@2
   148
	/// Changes to support 64-bit systems, memory management, and other corrections.
sl@0
   149
	/// Big thanks to Peter Nielsen.
sl@2
   150
	///
sl@0
   151
	/// </summary>
sl@0
   152
sl@0
   153
	internal class FrmMain
sl@0
   154
		: Form
sl@0
   155
	{
sl@0
   156
		#region '"Windows Form Designer generated code "'
sl@0
   157
		public FrmMain()
sl@0
   158
		//: base()
sl@0
   159
		{
sl@0
   160
			// This call is required by the Windows Form Designer.
sl@0
   161
			InitializeComponent();
sl@0
   162
		}
sl@0
   163
		// Form overrides dispose to clean up the component list.
sl@0
   164
		protected override void Dispose(bool Disposing1)
sl@0
   165
		{
sl@0
   166
			if (Disposing1)
sl@0
   167
			{
sl@0
   168
				if (components != null)
sl@0
   169
				{
sl@0
   170
					components.Dispose();
sl@0
   171
				}
sl@0
   172
			}
sl@0
   173
			base.Dispose(Disposing1);
sl@0
   174
		}
sl@0
   175
sl@0
   176
		// Required by the Windows Form Designer
sl@0
   177
		private System.ComponentModel.IContainer components;
sl@0
   178
		public System.Windows.Forms.ToolTip ToolTip1;
sl@0
   179
		public System.Windows.Forms.TextBox TxtBytesReceived;
sl@0
   180
		public System.Windows.Forms.GroupBox FraBytesReceived;
sl@0
   181
		public System.Windows.Forms.CheckBox ChkAutoincrement;
sl@0
   182
		public System.Windows.Forms.ComboBox CboByte1;
sl@0
   183
		public System.Windows.Forms.ComboBox CboByte0;
sl@0
   184
		public System.Windows.Forms.GroupBox FraBytesToSend;
sl@0
   185
		public System.Windows.Forms.ListBox LstResults;
sl@0
   186
		// NOTE: The following procedure is required by the Windows Form Designer
sl@0
   187
		// It can be modified using the Windows Form Designer.
sl@2
   188
		// Do not modify it using the code editor.
sl@0
   189
		internal System.Windows.Forms.GroupBox fraInputReportBufferSize;
sl@0
   190
		internal System.Windows.Forms.TextBox txtInputReportBufferSize;
sl@0
   191
		internal System.Windows.Forms.Button cmdInputReportBufferSize;
sl@0
   192
		internal System.Windows.Forms.GroupBox fraDeviceIdentifiers;
sl@0
   193
		internal System.Windows.Forms.Label lblVendorID;
sl@0
   194
		internal System.Windows.Forms.TextBox txtVendorID;
sl@0
   195
		internal System.Windows.Forms.Label lblProductID;
sl@0
   196
		internal System.Windows.Forms.TextBox txtProductID;
sl@0
   197
		internal System.Windows.Forms.Button cmdFindDevice;
sl@0
   198
		private Button cmdGetInputReportInterrupt;
sl@0
   199
		public GroupBox fraInterruptTransfers;
sl@0
   200
		private Button cmdSendOutputReportControl;
sl@0
   201
		private Button cmdGetInputReportControl;
sl@0
   202
		public GroupBox fraControlTransfers;
sl@0
   203
		private Button cmdGetFeatureReport;
sl@0
   204
		private Button cmdSendFeatureReport;
sl@0
   205
		private Button cmdPeriodicTransfers;
sl@0
   206
		public GroupBox fraSendAndGetContinuous;
sl@0
   207
		private RadioButton radFeature;
sl@0
   208
		private RadioButton radInputOutputControl;
sl@0
   209
		private RadioButton radInputOutputInterrupt;
sl@3
   210
        private TreeView treeViewDevices;
sl@0
   211
		private Button cmdSendOutputReportInterrupt;
sl@0
   212
sl@0
   213
		[System.Diagnostics.DebuggerStepThrough()]
sl@0
   214
		private void InitializeComponent()
sl@0
   215
		{
sl@3
   216
            this.components = new System.ComponentModel.Container();
sl@3
   217
            this.ToolTip1 = new System.Windows.Forms.ToolTip(this.components);
sl@3
   218
            this.FraBytesReceived = new System.Windows.Forms.GroupBox();
sl@3
   219
            this.TxtBytesReceived = new System.Windows.Forms.TextBox();
sl@3
   220
            this.FraBytesToSend = new System.Windows.Forms.GroupBox();
sl@3
   221
            this.ChkAutoincrement = new System.Windows.Forms.CheckBox();
sl@3
   222
            this.CboByte1 = new System.Windows.Forms.ComboBox();
sl@3
   223
            this.CboByte0 = new System.Windows.Forms.ComboBox();
sl@3
   224
            this.LstResults = new System.Windows.Forms.ListBox();
sl@3
   225
            this.fraInputReportBufferSize = new System.Windows.Forms.GroupBox();
sl@3
   226
            this.cmdInputReportBufferSize = new System.Windows.Forms.Button();
sl@3
   227
            this.txtInputReportBufferSize = new System.Windows.Forms.TextBox();
sl@3
   228
            this.fraDeviceIdentifiers = new System.Windows.Forms.GroupBox();
sl@3
   229
            this.txtProductID = new System.Windows.Forms.TextBox();
sl@3
   230
            this.lblProductID = new System.Windows.Forms.Label();
sl@3
   231
            this.txtVendorID = new System.Windows.Forms.TextBox();
sl@3
   232
            this.lblVendorID = new System.Windows.Forms.Label();
sl@3
   233
            this.cmdFindDevice = new System.Windows.Forms.Button();
sl@3
   234
            this.cmdSendOutputReportInterrupt = new System.Windows.Forms.Button();
sl@3
   235
            this.cmdGetInputReportInterrupt = new System.Windows.Forms.Button();
sl@3
   236
            this.fraInterruptTransfers = new System.Windows.Forms.GroupBox();
sl@3
   237
            this.cmdPeriodicTransfers = new System.Windows.Forms.Button();
sl@3
   238
            this.cmdSendOutputReportControl = new System.Windows.Forms.Button();
sl@3
   239
            this.cmdGetInputReportControl = new System.Windows.Forms.Button();
sl@3
   240
            this.fraControlTransfers = new System.Windows.Forms.GroupBox();
sl@3
   241
            this.cmdGetFeatureReport = new System.Windows.Forms.Button();
sl@3
   242
            this.cmdSendFeatureReport = new System.Windows.Forms.Button();
sl@3
   243
            this.fraSendAndGetContinuous = new System.Windows.Forms.GroupBox();
sl@3
   244
            this.radFeature = new System.Windows.Forms.RadioButton();
sl@3
   245
            this.radInputOutputControl = new System.Windows.Forms.RadioButton();
sl@3
   246
            this.radInputOutputInterrupt = new System.Windows.Forms.RadioButton();
sl@3
   247
            this.treeViewDevices = new System.Windows.Forms.TreeView();
sl@3
   248
            this.FraBytesReceived.SuspendLayout();
sl@3
   249
            this.FraBytesToSend.SuspendLayout();
sl@3
   250
            this.fraInputReportBufferSize.SuspendLayout();
sl@3
   251
            this.fraDeviceIdentifiers.SuspendLayout();
sl@3
   252
            this.fraInterruptTransfers.SuspendLayout();
sl@3
   253
            this.fraControlTransfers.SuspendLayout();
sl@3
   254
            this.fraSendAndGetContinuous.SuspendLayout();
sl@3
   255
            this.SuspendLayout();
sl@3
   256
            //
sl@3
   257
            // FraBytesReceived
sl@3
   258
            //
sl@3
   259
            this.FraBytesReceived.BackColor = System.Drawing.SystemColors.Control;
sl@3
   260
            this.FraBytesReceived.Controls.Add(this.TxtBytesReceived);
sl@3
   261
            this.FraBytesReceived.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   262
            this.FraBytesReceived.ForeColor = System.Drawing.SystemColors.ControlText;
sl@3
   263
            this.FraBytesReceived.Location = new System.Drawing.Point(495, 353);
sl@3
   264
            this.FraBytesReceived.Name = "FraBytesReceived";
sl@3
   265
            this.FraBytesReceived.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   266
            this.FraBytesReceived.Size = new System.Drawing.Size(112, 136);
sl@3
   267
            this.FraBytesReceived.TabIndex = 4;
sl@3
   268
            this.FraBytesReceived.TabStop = false;
sl@3
   269
            this.FraBytesReceived.Text = "Bytes Received";
sl@3
   270
            //
sl@3
   271
            // TxtBytesReceived
sl@3
   272
            //
sl@3
   273
            this.TxtBytesReceived.AcceptsReturn = true;
sl@3
   274
            this.TxtBytesReceived.BackColor = System.Drawing.SystemColors.Window;
sl@3
   275
            this.TxtBytesReceived.Cursor = System.Windows.Forms.Cursors.IBeam;
sl@3
   276
            this.TxtBytesReceived.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   277
            this.TxtBytesReceived.ForeColor = System.Drawing.SystemColors.WindowText;
sl@3
   278
            this.TxtBytesReceived.Location = new System.Drawing.Point(18, 24);
sl@3
   279
            this.TxtBytesReceived.MaxLength = 0;
sl@3
   280
            this.TxtBytesReceived.Multiline = true;
sl@3
   281
            this.TxtBytesReceived.Name = "TxtBytesReceived";
sl@3
   282
            this.TxtBytesReceived.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   283
            this.TxtBytesReceived.Size = new System.Drawing.Size(72, 96);
sl@3
   284
            this.TxtBytesReceived.TabIndex = 5;
sl@3
   285
            //
sl@3
   286
            // FraBytesToSend
sl@3
   287
            //
sl@3
   288
            this.FraBytesToSend.BackColor = System.Drawing.SystemColors.Control;
sl@3
   289
            this.FraBytesToSend.Controls.Add(this.ChkAutoincrement);
sl@3
   290
            this.FraBytesToSend.Controls.Add(this.CboByte1);
sl@3
   291
            this.FraBytesToSend.Controls.Add(this.CboByte0);
sl@3
   292
            this.FraBytesToSend.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   293
            this.FraBytesToSend.ForeColor = System.Drawing.SystemColors.ControlText;
sl@3
   294
            this.FraBytesToSend.Location = new System.Drawing.Point(612, 235);
sl@3
   295
            this.FraBytesToSend.Name = "FraBytesToSend";
sl@3
   296
            this.FraBytesToSend.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   297
            this.FraBytesToSend.Size = new System.Drawing.Size(160, 136);
sl@3
   298
            this.FraBytesToSend.TabIndex = 1;
sl@3
   299
            this.FraBytesToSend.TabStop = false;
sl@3
   300
            this.FraBytesToSend.Text = "Bytes to Send";
sl@3
   301
            //
sl@3
   302
            // ChkAutoincrement
sl@3
   303
            //
sl@3
   304
            this.ChkAutoincrement.BackColor = System.Drawing.SystemColors.Control;
sl@3
   305
            this.ChkAutoincrement.Cursor = System.Windows.Forms.Cursors.Default;
sl@3
   306
            this.ChkAutoincrement.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   307
            this.ChkAutoincrement.ForeColor = System.Drawing.SystemColors.ControlText;
sl@3
   308
            this.ChkAutoincrement.Location = new System.Drawing.Point(8, 96);
sl@3
   309
            this.ChkAutoincrement.Name = "ChkAutoincrement";
sl@3
   310
            this.ChkAutoincrement.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   311
            this.ChkAutoincrement.Size = new System.Drawing.Size(201, 35);
sl@3
   312
            this.ChkAutoincrement.TabIndex = 6;
sl@3
   313
            this.ChkAutoincrement.Text = "Autoincrement values";
sl@3
   314
            this.ChkAutoincrement.UseVisualStyleBackColor = false;
sl@3
   315
            //
sl@3
   316
            // CboByte1
sl@3
   317
            //
sl@3
   318
            this.CboByte1.BackColor = System.Drawing.SystemColors.Window;
sl@3
   319
            this.CboByte1.Cursor = System.Windows.Forms.Cursors.Default;
sl@3
   320
            this.CboByte1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
sl@3
   321
            this.CboByte1.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   322
            this.CboByte1.ForeColor = System.Drawing.SystemColors.WindowText;
sl@3
   323
            this.CboByte1.Location = new System.Drawing.Point(8, 64);
sl@3
   324
            this.CboByte1.Name = "CboByte1";
sl@3
   325
            this.CboByte1.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   326
            this.CboByte1.Size = new System.Drawing.Size(101, 22);
sl@3
   327
            this.CboByte1.TabIndex = 3;
sl@3
   328
            //
sl@3
   329
            // CboByte0
sl@3
   330
            //
sl@3
   331
            this.CboByte0.BackColor = System.Drawing.SystemColors.Window;
sl@3
   332
            this.CboByte0.Cursor = System.Windows.Forms.Cursors.Default;
sl@3
   333
            this.CboByte0.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
sl@3
   334
            this.CboByte0.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   335
            this.CboByte0.ForeColor = System.Drawing.SystemColors.WindowText;
sl@3
   336
            this.CboByte0.Location = new System.Drawing.Point(8, 24);
sl@3
   337
            this.CboByte0.Name = "CboByte0";
sl@3
   338
            this.CboByte0.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   339
            this.CboByte0.Size = new System.Drawing.Size(101, 22);
sl@3
   340
            this.CboByte0.TabIndex = 2;
sl@3
   341
            //
sl@3
   342
            // LstResults
sl@3
   343
            //
sl@3
   344
            this.LstResults.BackColor = System.Drawing.SystemColors.Window;
sl@3
   345
            this.LstResults.Cursor = System.Windows.Forms.Cursors.Default;
sl@3
   346
            this.LstResults.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   347
            this.LstResults.ForeColor = System.Drawing.SystemColors.WindowText;
sl@3
   348
            this.LstResults.HorizontalScrollbar = true;
sl@3
   349
            this.LstResults.ItemHeight = 14;
sl@3
   350
            this.LstResults.Location = new System.Drawing.Point(12, 494);
sl@3
   351
            this.LstResults.Name = "LstResults";
sl@3
   352
            this.LstResults.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   353
            this.LstResults.Size = new System.Drawing.Size(760, 256);
sl@3
   354
            this.LstResults.TabIndex = 0;
sl@3
   355
            //
sl@3
   356
            // fraInputReportBufferSize
sl@3
   357
            //
sl@3
   358
            this.fraInputReportBufferSize.Controls.Add(this.cmdInputReportBufferSize);
sl@3
   359
            this.fraInputReportBufferSize.Controls.Add(this.txtInputReportBufferSize);
sl@3
   360
            this.fraInputReportBufferSize.Location = new System.Drawing.Point(623, 44);
sl@3
   361
            this.fraInputReportBufferSize.Name = "fraInputReportBufferSize";
sl@3
   362
            this.fraInputReportBufferSize.Size = new System.Drawing.Size(149, 79);
sl@3
   363
            this.fraInputReportBufferSize.TabIndex = 9;
sl@3
   364
            this.fraInputReportBufferSize.TabStop = false;
sl@3
   365
            this.fraInputReportBufferSize.Text = "Input Report Buffer Size";
sl@3
   366
            //
sl@3
   367
            // cmdInputReportBufferSize
sl@3
   368
            //
sl@3
   369
            this.cmdInputReportBufferSize.Location = new System.Drawing.Point(6, 47);
sl@3
   370
            this.cmdInputReportBufferSize.Name = "cmdInputReportBufferSize";
sl@3
   371
            this.cmdInputReportBufferSize.Size = new System.Drawing.Size(136, 26);
sl@3
   372
            this.cmdInputReportBufferSize.TabIndex = 1;
sl@3
   373
            this.cmdInputReportBufferSize.Text = "Change Buffer Size";
sl@3
   374
            this.cmdInputReportBufferSize.Click += new System.EventHandler(this.cmdInputReportBufferSize_Click);
sl@3
   375
            //
sl@3
   376
            // txtInputReportBufferSize
sl@3
   377
            //
sl@3
   378
            this.txtInputReportBufferSize.Location = new System.Drawing.Point(6, 21);
sl@3
   379
            this.txtInputReportBufferSize.Name = "txtInputReportBufferSize";
sl@3
   380
            this.txtInputReportBufferSize.Size = new System.Drawing.Size(56, 20);
sl@3
   381
            this.txtInputReportBufferSize.TabIndex = 0;
sl@3
   382
            //
sl@3
   383
            // fraDeviceIdentifiers
sl@3
   384
            //
sl@3
   385
            this.fraDeviceIdentifiers.Controls.Add(this.txtProductID);
sl@3
   386
            this.fraDeviceIdentifiers.Controls.Add(this.lblProductID);
sl@3
   387
            this.fraDeviceIdentifiers.Controls.Add(this.txtVendorID);
sl@3
   388
            this.fraDeviceIdentifiers.Controls.Add(this.lblVendorID);
sl@3
   389
            this.fraDeviceIdentifiers.Location = new System.Drawing.Point(409, 12);
sl@3
   390
            this.fraDeviceIdentifiers.Name = "fraDeviceIdentifiers";
sl@3
   391
            this.fraDeviceIdentifiers.Size = new System.Drawing.Size(208, 96);
sl@3
   392
            this.fraDeviceIdentifiers.TabIndex = 10;
sl@3
   393
            this.fraDeviceIdentifiers.TabStop = false;
sl@3
   394
            this.fraDeviceIdentifiers.Text = "Device Identifiers";
sl@3
   395
            //
sl@3
   396
            // txtProductID
sl@3
   397
            //
sl@3
   398
            this.txtProductID.Location = new System.Drawing.Point(120, 56);
sl@3
   399
            this.txtProductID.Name = "txtProductID";
sl@3
   400
            this.txtProductID.Size = new System.Drawing.Size(72, 20);
sl@3
   401
            this.txtProductID.TabIndex = 3;
sl@3
   402
            this.txtProductID.Text = "1299";
sl@3
   403
            this.txtProductID.TextChanged += new System.EventHandler(this.txtProductID_TextChanged);
sl@3
   404
            //
sl@3
   405
            // lblProductID
sl@3
   406
            //
sl@3
   407
            this.lblProductID.Location = new System.Drawing.Point(16, 56);
sl@3
   408
            this.lblProductID.Name = "lblProductID";
sl@3
   409
            this.lblProductID.Size = new System.Drawing.Size(112, 23);
sl@3
   410
            this.lblProductID.TabIndex = 2;
sl@3
   411
            this.lblProductID.Text = "Product ID (hex):";
sl@3
   412
            //
sl@3
   413
            // txtVendorID
sl@3
   414
            //
sl@3
   415
            this.txtVendorID.Location = new System.Drawing.Point(120, 24);
sl@3
   416
            this.txtVendorID.Name = "txtVendorID";
sl@3
   417
            this.txtVendorID.Size = new System.Drawing.Size(72, 20);
sl@3
   418
            this.txtVendorID.TabIndex = 1;
sl@3
   419
            this.txtVendorID.Text = "0925";
sl@3
   420
            this.txtVendorID.TextChanged += new System.EventHandler(this.txtVendorID_TextChanged);
sl@3
   421
            //
sl@3
   422
            // lblVendorID
sl@3
   423
            //
sl@3
   424
            this.lblVendorID.Location = new System.Drawing.Point(16, 24);
sl@3
   425
            this.lblVendorID.Name = "lblVendorID";
sl@3
   426
            this.lblVendorID.Size = new System.Drawing.Size(112, 23);
sl@3
   427
            this.lblVendorID.TabIndex = 0;
sl@3
   428
            this.lblVendorID.Text = "Vendor ID (hex):";
sl@3
   429
            //
sl@3
   430
            // cmdFindDevice
sl@3
   431
            //
sl@3
   432
            this.cmdFindDevice.Location = new System.Drawing.Point(636, 12);
sl@3
   433
            this.cmdFindDevice.Name = "cmdFindDevice";
sl@3
   434
            this.cmdFindDevice.Size = new System.Drawing.Size(136, 26);
sl@3
   435
            this.cmdFindDevice.TabIndex = 11;
sl@3
   436
            this.cmdFindDevice.Text = "Find My Device";
sl@3
   437
            this.cmdFindDevice.Click += new System.EventHandler(this.cmdFindDevice_Click);
sl@3
   438
            //
sl@3
   439
            // cmdSendOutputReportInterrupt
sl@3
   440
            //
sl@3
   441
            this.cmdSendOutputReportInterrupt.Location = new System.Drawing.Point(21, 27);
sl@3
   442
            this.cmdSendOutputReportInterrupt.Name = "cmdSendOutputReportInterrupt";
sl@3
   443
            this.cmdSendOutputReportInterrupt.Size = new System.Drawing.Size(118, 26);
sl@3
   444
            this.cmdSendOutputReportInterrupt.TabIndex = 12;
sl@3
   445
            this.cmdSendOutputReportInterrupt.Text = "Send Output Report";
sl@3
   446
            this.cmdSendOutputReportInterrupt.UseVisualStyleBackColor = true;
sl@3
   447
            this.cmdSendOutputReportInterrupt.Click += new System.EventHandler(this.cmdSendOutputReportInterrupt_Click);
sl@3
   448
            //
sl@3
   449
            // cmdGetInputReportInterrupt
sl@3
   450
            //
sl@3
   451
            this.cmdGetInputReportInterrupt.Location = new System.Drawing.Point(21, 60);
sl@3
   452
            this.cmdGetInputReportInterrupt.Name = "cmdGetInputReportInterrupt";
sl@3
   453
            this.cmdGetInputReportInterrupt.Size = new System.Drawing.Size(118, 26);
sl@3
   454
            this.cmdGetInputReportInterrupt.TabIndex = 13;
sl@3
   455
            this.cmdGetInputReportInterrupt.Text = "Get Input Report";
sl@3
   456
            this.cmdGetInputReportInterrupt.UseVisualStyleBackColor = true;
sl@3
   457
            this.cmdGetInputReportInterrupt.Click += new System.EventHandler(this.cmdGetInputReportInterrupt_Click);
sl@3
   458
            //
sl@3
   459
            // fraInterruptTransfers
sl@3
   460
            //
sl@3
   461
            this.fraInterruptTransfers.BackColor = System.Drawing.SystemColors.Control;
sl@3
   462
            this.fraInterruptTransfers.Controls.Add(this.cmdSendOutputReportInterrupt);
sl@3
   463
            this.fraInterruptTransfers.Controls.Add(this.cmdGetInputReportInterrupt);
sl@3
   464
            this.fraInterruptTransfers.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   465
            this.fraInterruptTransfers.ForeColor = System.Drawing.SystemColors.ControlText;
sl@3
   466
            this.fraInterruptTransfers.Location = new System.Drawing.Point(338, 129);
sl@3
   467
            this.fraInterruptTransfers.Name = "fraInterruptTransfers";
sl@3
   468
            this.fraInterruptTransfers.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   469
            this.fraInterruptTransfers.Size = new System.Drawing.Size(151, 100);
sl@3
   470
            this.fraInterruptTransfers.TabIndex = 14;
sl@3
   471
            this.fraInterruptTransfers.TabStop = false;
sl@3
   472
            this.fraInterruptTransfers.Text = "Interrupt Transfers";
sl@3
   473
            //
sl@3
   474
            // cmdPeriodicTransfers
sl@3
   475
            //
sl@3
   476
            this.cmdPeriodicTransfers.Location = new System.Drawing.Point(153, 36);
sl@3
   477
            this.cmdPeriodicTransfers.Name = "cmdPeriodicTransfers";
sl@3
   478
            this.cmdPeriodicTransfers.Size = new System.Drawing.Size(118, 26);
sl@3
   479
            this.cmdPeriodicTransfers.TabIndex = 16;
sl@3
   480
            this.cmdPeriodicTransfers.Text = "Start";
sl@3
   481
            this.cmdPeriodicTransfers.UseVisualStyleBackColor = true;
sl@3
   482
            this.cmdPeriodicTransfers.Click += new System.EventHandler(this.cmdPeriodicTransfers_Click);
sl@3
   483
            //
sl@3
   484
            // cmdSendOutputReportControl
sl@3
   485
            //
sl@3
   486
            this.cmdSendOutputReportControl.Location = new System.Drawing.Point(10, 27);
sl@3
   487
            this.cmdSendOutputReportControl.Name = "cmdSendOutputReportControl";
sl@3
   488
            this.cmdSendOutputReportControl.Size = new System.Drawing.Size(118, 26);
sl@3
   489
            this.cmdSendOutputReportControl.TabIndex = 12;
sl@3
   490
            this.cmdSendOutputReportControl.Text = "Send Output Report";
sl@3
   491
            this.cmdSendOutputReportControl.UseVisualStyleBackColor = true;
sl@3
   492
            this.cmdSendOutputReportControl.Click += new System.EventHandler(this.cmdSendOutputReportControl_Click);
sl@3
   493
            //
sl@3
   494
            // cmdGetInputReportControl
sl@3
   495
            //
sl@3
   496
            this.cmdGetInputReportControl.Location = new System.Drawing.Point(10, 60);
sl@3
   497
            this.cmdGetInputReportControl.Name = "cmdGetInputReportControl";
sl@3
   498
            this.cmdGetInputReportControl.Size = new System.Drawing.Size(118, 26);
sl@3
   499
            this.cmdGetInputReportControl.TabIndex = 13;
sl@3
   500
            this.cmdGetInputReportControl.Text = "Get Input Report";
sl@3
   501
            this.cmdGetInputReportControl.UseVisualStyleBackColor = true;
sl@3
   502
            this.cmdGetInputReportControl.Click += new System.EventHandler(this.cmdGetInputReportControl_Click);
sl@3
   503
            //
sl@3
   504
            // fraControlTransfers
sl@3
   505
            //
sl@3
   506
            this.fraControlTransfers.BackColor = System.Drawing.SystemColors.Control;
sl@3
   507
            this.fraControlTransfers.Controls.Add(this.cmdGetFeatureReport);
sl@3
   508
            this.fraControlTransfers.Controls.Add(this.cmdSendFeatureReport);
sl@3
   509
            this.fraControlTransfers.Controls.Add(this.cmdSendOutputReportControl);
sl@3
   510
            this.fraControlTransfers.Controls.Add(this.cmdGetInputReportControl);
sl@3
   511
            this.fraControlTransfers.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   512
            this.fraControlTransfers.ForeColor = System.Drawing.SystemColors.ControlText;
sl@3
   513
            this.fraControlTransfers.Location = new System.Drawing.Point(495, 129);
sl@3
   514
            this.fraControlTransfers.Name = "fraControlTransfers";
sl@3
   515
            this.fraControlTransfers.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   516
            this.fraControlTransfers.Size = new System.Drawing.Size(277, 100);
sl@3
   517
            this.fraControlTransfers.TabIndex = 15;
sl@3
   518
            this.fraControlTransfers.TabStop = false;
sl@3
   519
            this.fraControlTransfers.Text = "Control Transfers";
sl@3
   520
            //
sl@3
   521
            // cmdGetFeatureReport
sl@3
   522
            //
sl@3
   523
            this.cmdGetFeatureReport.Location = new System.Drawing.Point(141, 60);
sl@3
   524
            this.cmdGetFeatureReport.Name = "cmdGetFeatureReport";
sl@3
   525
            this.cmdGetFeatureReport.Size = new System.Drawing.Size(118, 26);
sl@3
   526
            this.cmdGetFeatureReport.TabIndex = 15;
sl@3
   527
            this.cmdGetFeatureReport.Text = "Get Feature Report";
sl@3
   528
            this.cmdGetFeatureReport.UseVisualStyleBackColor = true;
sl@3
   529
            this.cmdGetFeatureReport.Click += new System.EventHandler(this.cmdGetFeatureReport_Click);
sl@3
   530
            //
sl@3
   531
            // cmdSendFeatureReport
sl@3
   532
            //
sl@3
   533
            this.cmdSendFeatureReport.Location = new System.Drawing.Point(141, 27);
sl@3
   534
            this.cmdSendFeatureReport.Name = "cmdSendFeatureReport";
sl@3
   535
            this.cmdSendFeatureReport.Size = new System.Drawing.Size(118, 26);
sl@3
   536
            this.cmdSendFeatureReport.TabIndex = 14;
sl@3
   537
            this.cmdSendFeatureReport.Text = "Send Feature Report";
sl@3
   538
            this.cmdSendFeatureReport.UseVisualStyleBackColor = true;
sl@3
   539
            this.cmdSendFeatureReport.Click += new System.EventHandler(this.cmdSendFeatureReport_Click);
sl@3
   540
            //
sl@3
   541
            // fraSendAndGetContinuous
sl@3
   542
            //
sl@3
   543
            this.fraSendAndGetContinuous.BackColor = System.Drawing.SystemColors.Control;
sl@3
   544
            this.fraSendAndGetContinuous.Controls.Add(this.radFeature);
sl@3
   545
            this.fraSendAndGetContinuous.Controls.Add(this.radInputOutputControl);
sl@3
   546
            this.fraSendAndGetContinuous.Controls.Add(this.radInputOutputInterrupt);
sl@3
   547
            this.fraSendAndGetContinuous.Controls.Add(this.cmdPeriodicTransfers);
sl@3
   548
            this.fraSendAndGetContinuous.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   549
            this.fraSendAndGetContinuous.ForeColor = System.Drawing.SystemColors.ControlText;
sl@3
   550
            this.fraSendAndGetContinuous.Location = new System.Drawing.Point(311, 235);
sl@3
   551
            this.fraSendAndGetContinuous.Name = "fraSendAndGetContinuous";
sl@3
   552
            this.fraSendAndGetContinuous.RightToLeft = System.Windows.Forms.RightToLeft.No;
sl@3
   553
            this.fraSendAndGetContinuous.Size = new System.Drawing.Size(295, 112);
sl@3
   554
            this.fraSendAndGetContinuous.TabIndex = 17;
sl@3
   555
            this.fraSendAndGetContinuous.TabStop = false;
sl@3
   556
            this.fraSendAndGetContinuous.Text = "Send and Get Continuous";
sl@3
   557
            //
sl@3
   558
            // radFeature
sl@3
   559
            //
sl@3
   560
            this.radFeature.AutoSize = true;
sl@3
   561
            this.radFeature.Location = new System.Drawing.Point(17, 76);
sl@3
   562
            this.radFeature.Name = "radFeature";
sl@3
   563
            this.radFeature.Size = new System.Drawing.Size(62, 18);
sl@3
   564
            this.radFeature.TabIndex = 19;
sl@3
   565
            this.radFeature.TabStop = true;
sl@3
   566
            this.radFeature.Text = "Feature";
sl@3
   567
            this.radFeature.UseVisualStyleBackColor = true;
sl@3
   568
            this.radFeature.CheckedChanged += new System.EventHandler(this.radFeature_CheckedChanged);
sl@3
   569
            //
sl@3
   570
            // radInputOutputControl
sl@3
   571
            //
sl@3
   572
            this.radInputOutputControl.AutoSize = true;
sl@3
   573
            this.radInputOutputControl.Location = new System.Drawing.Point(17, 52);
sl@3
   574
            this.radInputOutputControl.Name = "radInputOutputControl";
sl@3
   575
            this.radInputOutputControl.Size = new System.Drawing.Size(120, 18);
sl@3
   576
            this.radInputOutputControl.TabIndex = 18;
sl@3
   577
            this.radInputOutputControl.TabStop = true;
sl@3
   578
            this.radInputOutputControl.Text = "Input Output Control";
sl@3
   579
            this.radInputOutputControl.UseVisualStyleBackColor = true;
sl@3
   580
            this.radInputOutputControl.CheckedChanged += new System.EventHandler(this.radInputOutputControl_CheckedChanged);
sl@3
   581
            //
sl@3
   582
            // radInputOutputInterrupt
sl@3
   583
            //
sl@3
   584
            this.radInputOutputInterrupt.AutoSize = true;
sl@3
   585
            this.radInputOutputInterrupt.Location = new System.Drawing.Point(17, 28);
sl@3
   586
            this.radInputOutputInterrupt.Name = "radInputOutputInterrupt";
sl@3
   587
            this.radInputOutputInterrupt.Size = new System.Drawing.Size(126, 18);
sl@3
   588
            this.radInputOutputInterrupt.TabIndex = 17;
sl@3
   589
            this.radInputOutputInterrupt.TabStop = true;
sl@3
   590
            this.radInputOutputInterrupt.Text = "Input Output Interrupt";
sl@3
   591
            this.radInputOutputInterrupt.UseVisualStyleBackColor = true;
sl@3
   592
            this.radInputOutputInterrupt.CheckedChanged += new System.EventHandler(this.radInputOutputInterrupt_CheckedChanged);
sl@3
   593
            //
sl@3
   594
            // treeViewDevices
sl@3
   595
            //
sl@3
   596
            this.treeViewDevices.Location = new System.Drawing.Point(12, 12);
sl@3
   597
            this.treeViewDevices.Name = "treeViewDevices";
sl@3
   598
            this.treeViewDevices.Size = new System.Drawing.Size(284, 461);
sl@3
   599
            this.treeViewDevices.TabIndex = 18;
sl@3
   600
            //
sl@3
   601
            // FrmMain
sl@3
   602
            //
sl@3
   603
            this.ClientSize = new System.Drawing.Size(784, 756);
sl@3
   604
            this.Controls.Add(this.treeViewDevices);
sl@3
   605
            this.Controls.Add(this.fraSendAndGetContinuous);
sl@3
   606
            this.Controls.Add(this.fraControlTransfers);
sl@3
   607
            this.Controls.Add(this.fraInterruptTransfers);
sl@3
   608
            this.Controls.Add(this.cmdFindDevice);
sl@3
   609
            this.Controls.Add(this.fraDeviceIdentifiers);
sl@3
   610
            this.Controls.Add(this.fraInputReportBufferSize);
sl@3
   611
            this.Controls.Add(this.FraBytesReceived);
sl@3
   612
            this.Controls.Add(this.FraBytesToSend);
sl@3
   613
            this.Controls.Add(this.LstResults);
sl@3
   614
            this.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
sl@3
   615
            this.Location = new System.Drawing.Point(21, 28);
sl@3
   616
            this.Name = "FrmMain";
sl@3
   617
            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
sl@3
   618
            this.Text = "Generic HID Tester";
sl@3
   619
            this.Closed += new System.EventHandler(this.frmMain_Closed);
sl@3
   620
            this.Load += new System.EventHandler(this.frmMain_Load);
sl@3
   621
            this.FraBytesReceived.ResumeLayout(false);
sl@3
   622
            this.FraBytesReceived.PerformLayout();
sl@3
   623
            this.FraBytesToSend.ResumeLayout(false);
sl@3
   624
            this.fraInputReportBufferSize.ResumeLayout(false);
sl@3
   625
            this.fraInputReportBufferSize.PerformLayout();
sl@3
   626
            this.fraDeviceIdentifiers.ResumeLayout(false);
sl@3
   627
            this.fraDeviceIdentifiers.PerformLayout();
sl@3
   628
            this.fraInterruptTransfers.ResumeLayout(false);
sl@3
   629
            this.fraControlTransfers.ResumeLayout(false);
sl@3
   630
            this.fraSendAndGetContinuous.ResumeLayout(false);
sl@3
   631
            this.fraSendAndGetContinuous.PerformLayout();
sl@3
   632
            this.ResumeLayout(false);
sl@0
   633
sl@0
   634
		}
sl@2
   635
		#endregion '"Windows Form Designer generated code "'
sl@0
   636
sl@0
   637
		private Boolean _deviceDetected;
sl@0
   638
		private IntPtr _deviceNotificationHandle;
sl@0
   639
		private FileStream _deviceData;
sl@0
   640
		private FormActions _formActions;
sl@0
   641
		private SafeFileHandle _hidHandle;
sl@0
   642
		private String _hidUsage;
sl@0
   643
		private ManagementEventWatcher _deviceArrivedWatcher;
sl@0
   644
		private Boolean _deviceHandleObtained;
sl@0
   645
		private ManagementEventWatcher _deviceRemovedWatcher;
sl@0
   646
		private Int32 _myProductId;
sl@0
   647
		private Int32 _myVendorId;
sl@0
   648
		private Boolean _periodicTransfersRequested;
sl@0
   649
		private ReportReadOrWritten _readOrWritten;
sl@0
   650
		private ReportTypes _reportType;
sl@0
   651
		private SendOrGet _sendOrGet;
sl@0
   652
		private Boolean _transferInProgress;
sl@0
   653
		private TransferTypes _transferType;
sl@0
   654
sl@0
   655
		private static System.Timers.Timer _periodicTransfers;
sl@0
   656
sl@0
   657
		private readonly Debugging _myDebugging = new Debugging(); //  For viewing results of API calls via Debug.Write.
sl@0
   658
		private readonly DeviceManagement _myDeviceManagement = new DeviceManagement();
sl@0
   659
		private Hid _myHid = new Hid();
sl@0
   660
sl@0
   661
		private enum FormActions
sl@0
   662
		{
sl@0
   663
			AddItemToListBox,
sl@0
   664
			DisableInputReportBufferSize,
sl@0
   665
			EnableGetInputReportInterruptTransfer,
sl@0
   666
			EnableInputReportBufferSize,
sl@0
   667
			EnableSendOutputReportInterrupt,
sl@0
   668
			ScrollToBottomOfListBox,
sl@3
   669
			SetInputReportBufferSize,
sl@3
   670
            AddDeviceToTreeView,
sl@3
   671
            ResetDeviceTreeView,
sl@4
   672
            SelectDeviceInTreeView,
sl@4
   673
            CompleteDeviceTreeView
sl@0
   674
		}
sl@0
   675
sl@0
   676
		private enum ReportReadOrWritten
sl@0
   677
		{
sl@0
   678
			Read,
sl@0
   679
			Written
sl@0
   680
		}
sl@0
   681
sl@0
   682
		private enum ReportTypes
sl@0
   683
		{
sl@0
   684
			Input,
sl@0
   685
			Output,
sl@0
   686
			Feature
sl@0
   687
		}
sl@0
   688
sl@0
   689
		private enum SendOrGet
sl@0
   690
		{
sl@0
   691
			Send,
sl@0
   692
			Get
sl@0
   693
		}
sl@0
   694
sl@0
   695
		private enum TransferTypes
sl@0
   696
		{
sl@0
   697
			Control,
sl@0
   698
			Interrupt
sl@0
   699
		}
sl@0
   700
sl@0
   701
		private enum WmiDeviceProperties
sl@0
   702
		{
sl@0
   703
			Name,
sl@0
   704
			Caption,
sl@0
   705
			Description,
sl@0
   706
			Manufacturer,
sl@0
   707
			PNPDeviceID,
sl@0
   708
			DeviceID,
sl@0
   709
			ClassGUID
sl@0
   710
		}
sl@0
   711
sl@0
   712
		internal FrmMain FrmMy;
sl@0
   713
sl@0
   714
		//  This delegate has the same parameters as AccessForm.
sl@0
   715
		//  Used in accessing the application's form from a different thread.
sl@0
   716
sl@3
   717
        private delegate void MarshalDataToForm(FormActions action, params string[] strings);
sl@0
   718
sl@0
   719
		///  <summary>
sl@0
   720
		///  Performs various application-specific functions that
sl@0
   721
		///  involve accessing the application's form.
sl@0
   722
		///  </summary>
sl@2
   723
		///
sl@0
   724
		///  <param name="action"> a FormActions member that names the action to perform on the form</param>
sl@2
   725
		///  <param name="formText"> text that the form displays or the code uses for
sl@0
   726
		///  another purpose. Actions that don't use text ignore this parameter. </param>
sl@0
   727
sl@3
   728
		private void AccessForm(FormActions action, params string[] strings)
sl@0
   729
		{
sl@0
   730
			try
sl@0
   731
			{
sl@0
   732
				//  Select an action to perform on the form:
sl@0
   733
sl@0
   734
				switch (action)
sl@0
   735
				{
sl@0
   736
					case FormActions.AddItemToListBox:
sl@0
   737
sl@3
   738
                        LstResults.Items.Add(strings[0]);
sl@0
   739
						break;
sl@0
   740
sl@0
   741
					case FormActions.DisableInputReportBufferSize:
sl@0
   742
sl@0
   743
						cmdInputReportBufferSize.Enabled = false;
sl@0
   744
						break;
sl@0
   745
sl@0
   746
					case FormActions.EnableGetInputReportInterruptTransfer:
sl@0
   747
sl@0
   748
						cmdGetInputReportInterrupt.Enabled = true;
sl@0
   749
						break;
sl@0
   750
sl@0
   751
					case FormActions.EnableInputReportBufferSize:
sl@0
   752
sl@0
   753
						cmdInputReportBufferSize.Enabled = true;
sl@0
   754
						break;
sl@0
   755
sl@0
   756
					case FormActions.EnableSendOutputReportInterrupt:
sl@0
   757
sl@0
   758
						cmdSendOutputReportInterrupt.Enabled = true;
sl@0
   759
						break;
sl@0
   760
sl@0
   761
					case FormActions.ScrollToBottomOfListBox:
sl@0
   762
sl@0
   763
						LstResults.SelectedIndex = LstResults.Items.Count - 1;
sl@0
   764
						break;
sl@0
   765
sl@0
   766
					case FormActions.SetInputReportBufferSize:
sl@0
   767
sl@3
   768
                        txtInputReportBufferSize.Text = strings[0];
sl@0
   769
						break;
sl@3
   770
sl@3
   771
                    case FormActions.AddDeviceToTreeView:
sl@3
   772
                        {
sl@4
   773
                            //Try and see if our device is already present
sl@4
   774
                            TreeNode[] res = treeViewDevices.Nodes.Find(strings[0], false);
sl@4
   775
                            foreach (TreeNode device in res)
sl@3
   776
                            {
sl@4
   777
                                if (device.ForeColor == Color.Red)
sl@4
   778
                                {
sl@4
   779
                                    //Device was removed and has now been added back
sl@4
   780
                                    device.ForeColor = Color.Green;
sl@4
   781
                                }
sl@4
   782
                                else
sl@4
   783
                                {
sl@4
   784
                                    //Device was already there set back our device color to black
sl@4
   785
                                    device.ForeColor = Color.Black;
sl@4
   786
                                }
sl@3
   787
                            }
sl@4
   788
sl@4
   789
                            if (res.Length > 0)
sl@4
   790
                            {
sl@4
   791
                                //Our device is already there
sl@4
   792
                                break;
sl@4
   793
                            }
sl@4
   794
sl@4
   795
                            //Build our node from our string array
sl@4
   796
                            TreeNode newNode = new TreeNode(strings[0]);
sl@4
   797
                            for (int i = 1; i < strings.Length; i++)
sl@4
   798
                            {
sl@4
   799
                                newNode.Nodes.Add(strings[i]);
sl@4
   800
                                if (strings[i].StartsWith("Name: "))
sl@4
   801
                                {
sl@4
   802
                                    //Found our name property, update our node text
sl@4
   803
                                    newNode.Text = strings[i].Substring(6, strings[i].Length - 6);
sl@4
   804
                                }
sl@4
   805
                            }
sl@4
   806
sl@4
   807
                            //New device color is green
sl@4
   808
                            newNode.ForeColor = Color.Green;
sl@4
   809
                            newNode.Name = strings[0]; //Set ID as name to make sure we can find it
sl@4
   810
                            treeViewDevices.Nodes.Add(newNode);
sl@3
   811
                        }
sl@3
   812
                        break;
sl@3
   813
sl@3
   814
                    case FormActions.ResetDeviceTreeView:
sl@4
   815
                        {
sl@4
   816
                            //Mark all non removed/red device as purple/unknown
sl@4
   817
                            foreach (TreeNode device in treeViewDevices.Nodes)
sl@4
   818
                            {
sl@4
   819
                                if (device.ForeColor != Color.Red)
sl@4
   820
                                {
sl@4
   821
                                    device.ForeColor = Color.Purple;
sl@4
   822
                                }
sl@4
   823
                            }
sl@4
   824
                            //treeViewDevices.Nodes.Clear();
sl@4
   825
                        }
sl@4
   826
                        break;
sl@4
   827
sl@4
   828
                    case FormActions.CompleteDeviceTreeView:
sl@4
   829
                        {
sl@4
   830
                            //Our device list is now complete
sl@4
   831
                            foreach (TreeNode device in treeViewDevices.Nodes)
sl@4
   832
                            {
sl@4
   833
                                //Purple devices need to be marked as red for removed
sl@4
   834
                                if (device.ForeColor == Color.Purple)
sl@4
   835
                                {
sl@4
   836
                                    device.ForeColor = Color.Red;
sl@4
   837
                                }
sl@4
   838
                            }
sl@4
   839
                        }
sl@3
   840
                        break;
sl@3
   841
sl@3
   842
                    case FormActions.SelectDeviceInTreeView:
sl@3
   843
                        {
sl@4
   844
                            //treeViewDevices.SelectedNode = null;
sl@4
   845
                            TreeNode[] res = treeViewDevices.Nodes.Find(strings[0], false);
sl@4
   846
                            foreach (TreeNode device in res)
sl@4
   847
                            {
sl@4
   848
                                device.ForeColor = Color.Blue;
sl@4
   849
                                //treeViewDevices.SelectedNode = res[0];
sl@4
   850
                                //treeViewDevices.SelectedNode.ForeColor = Color.Blue;
sl@4
   851
                            }
sl@3
   852
                        }
sl@3
   853
sl@3
   854
sl@3
   855
                        break;
sl@0
   856
				}
sl@0
   857
			}
sl@0
   858
			catch (Exception ex)
sl@0
   859
			{
sl@0
   860
				DisplayException(Name, ex);
sl@0
   861
				throw;
sl@0
   862
			}
sl@0
   863
		}
sl@0
   864
sl@0
   865
		///  <summary>
sl@0
   866
		///  Add a handler to detect arrival of devices using WMI.
sl@0
   867
		///  </summary>
sl@0
   868
sl@0
   869
		private void AddDeviceArrivedHandler()
sl@0
   870
		{
sl@0
   871
			const Int32 pollingIntervalSeconds = 3;
sl@0
   872
			var scope = new ManagementScope("root\\CIMV2");
sl@0
   873
			scope.Options.EnablePrivileges = true;
sl@0
   874
sl@0
   875
			try
sl@0
   876
			{
sl@0
   877
				var q = new WqlEventQuery();
sl@0
   878
				q.EventClassName = "__InstanceCreationEvent";
sl@0
   879
				q.WithinInterval = new TimeSpan(0, 0, pollingIntervalSeconds);
sl@0
   880
				q.Condition = @"TargetInstance ISA 'Win32_USBControllerdevice'";
sl@0
   881
				_deviceArrivedWatcher = new ManagementEventWatcher(scope, q);
sl@0
   882
				_deviceArrivedWatcher.EventArrived += DeviceAdded;
sl@0
   883
sl@0
   884
				_deviceArrivedWatcher.Start();
sl@0
   885
			}
sl@0
   886
			catch (Exception e)
sl@0
   887
			{
sl@0
   888
				Debug.WriteLine(e.Message);
sl@0
   889
				if (_deviceArrivedWatcher != null)
sl@0
   890
					_deviceArrivedWatcher.Stop();
sl@0
   891
			}
sl@0
   892
		}
sl@0
   893
sl@0
   894
		///  <summary>
sl@0
   895
		///  Add a handler to detect removal of devices using WMI.
sl@0
   896
		///  </summary>
sl@0
   897
sl@0
   898
		private void AddDeviceRemovedHandler()
sl@0
   899
		{
sl@0
   900
			const Int32 pollingIntervalSeconds = 3;
sl@0
   901
			var scope = new ManagementScope("root\\CIMV2");
sl@0
   902
			scope.Options.EnablePrivileges = true;
sl@0
   903
sl@0
   904
			try
sl@0
   905
			{
sl@0
   906
				var q = new WqlEventQuery();
sl@0
   907
				q.EventClassName = "__InstanceDeletionEvent";
sl@0
   908
				q.WithinInterval = new TimeSpan(0, 0, pollingIntervalSeconds);
sl@0
   909
				q.Condition = @"TargetInstance ISA 'Win32_USBControllerdevice'";
sl@0
   910
				_deviceRemovedWatcher = new ManagementEventWatcher(scope, q);
sl@0
   911
				_deviceRemovedWatcher.EventArrived += DeviceRemoved;
sl@0
   912
				_deviceRemovedWatcher.Start();
sl@0
   913
			}
sl@0
   914
			catch (Exception e)
sl@0
   915
			{
sl@0
   916
				Debug.WriteLine(e.Message);
sl@0
   917
				if (_deviceRemovedWatcher != null)
sl@0
   918
					_deviceRemovedWatcher.Stop();
sl@0
   919
			}
sl@0
   920
		}
sl@0
   921
sl@0
   922
		/// <summary>
sl@0
   923
		/// Close the handle and FileStreams for a device.
sl@0
   924
		/// </summary>
sl@2
   925
		///
sl@0
   926
		private void CloseCommunications()
sl@0
   927
		{
sl@0
   928
			if (_deviceData != null)
sl@0
   929
			{
sl@0
   930
				_deviceData.Close();
sl@0
   931
			}
sl@0
   932
sl@0
   933
			if ((_hidHandle != null) && (!(_hidHandle.IsInvalid)))
sl@0
   934
			{
sl@0
   935
				_hidHandle.Close();
sl@0
   936
			}
sl@0
   937
sl@0
   938
			// The next attempt to communicate will get a new handle and FileStreams.
sl@0
   939
sl@0
   940
			_deviceHandleObtained = false;
sl@0
   941
		}
sl@0
   942
sl@0
   943
		///  <summary>
sl@0
   944
		///  Search for a specific device.
sl@0
   945
		///  </summary>
sl@0
   946
sl@0
   947
		private void cmdFindDevice_Click(Object sender, EventArgs e)
sl@0
   948
		{
sl@0
   949
			try
sl@0
   950
			{
sl@0
   951
				if (_transferInProgress)
sl@0
   952
				{
sl@0
   953
					DisplayTransferInProgressMessage();
sl@0
   954
				}
sl@0
   955
				else
sl@0
   956
				{
sl@0
   957
					_deviceDetected = FindDeviceUsingWmi();
sl@0
   958
					if (_deviceDetected)
sl@0
   959
					{
sl@0
   960
						FindTheHid();
sl@0
   961
					}
sl@0
   962
				}
sl@0
   963
			}
sl@0
   964
			catch (Exception ex)
sl@0
   965
			{
sl@0
   966
				DisplayException(Name, ex);
sl@0
   967
				throw;
sl@0
   968
			}
sl@0
   969
		}
sl@0
   970
sl@0
   971
		/// <summary>
sl@0
   972
		/// Request to get a Feature report from the device.
sl@0
   973
		/// </summary>
sl@0
   974
		/// <param name="sender"></param>
sl@0
   975
		/// <param name="e"></param>
sl@0
   976
sl@0
   977
		private void cmdGetFeatureReport_Click(object sender, EventArgs e)
sl@0
   978
		{
sl@0
   979
			try
sl@0
   980
			{
sl@0
   981
				if (_transferInProgress)
sl@0
   982
				{
sl@0
   983
					DisplayTransferInProgressMessage();
sl@0
   984
				}
sl@0
   985
				else
sl@0
   986
				{
sl@0
   987
					//  Don't allow another transfer request until this one completes.
sl@2
   988
					//  Move the focus away from the button to prevent the focus from
sl@0
   989
					//  switching to the next control in the tab order on disabling the button.
sl@0
   990
sl@0
   991
					fraControlTransfers.Focus();
sl@0
   992
					cmdGetFeatureReport.Enabled = false;
sl@0
   993
					_transferType = TransferTypes.Control;
sl@0
   994
					RequestToGetFeatureReport();
sl@0
   995
				}
sl@0
   996
			}
sl@0
   997
			catch (Exception ex)
sl@0
   998
			{
sl@0
   999
				DisplayException(Name, ex);
sl@0
  1000
				throw;
sl@0
  1001
			}
sl@0
  1002
		}
sl@0
  1003
sl@0
  1004
		/// <summary>
sl@0
  1005
		/// Request to get an Input report from the device using a control transfer.
sl@0
  1006
		/// </summary>
sl@0
  1007
		/// <param name="sender"></param>
sl@0
  1008
		/// <param name="e"></param>
sl@0
  1009
sl@0
  1010
		private void cmdGetInputReportControl_Click(object sender, EventArgs e)
sl@0
  1011
		{
sl@0
  1012
			try
sl@0
  1013
			{
sl@0
  1014
				//  Don't allow another transfer request until this one completes.
sl@2
  1015
				//  Move the focus away from the button to prevent the focus from
sl@0
  1016
				//  switching to the next control in the tab order on disabling the button.
sl@0
  1017
sl@0
  1018
				if (_transferInProgress)
sl@0
  1019
				{
sl@0
  1020
					DisplayTransferInProgressMessage();
sl@0
  1021
				}
sl@0
  1022
				else
sl@0
  1023
				{
sl@0
  1024
					fraControlTransfers.Focus();
sl@0
  1025
					cmdGetInputReportControl.Enabled = false;
sl@0
  1026
					_transferType = TransferTypes.Control;
sl@0
  1027
					RequestToGetInputReport();
sl@0
  1028
				}
sl@0
  1029
			}
sl@0
  1030
			catch (Exception ex)
sl@0
  1031
			{
sl@0
  1032
				DisplayException(Name, ex);
sl@0
  1033
				throw;
sl@0
  1034
			}
sl@0
  1035
		}
sl@0
  1036
sl@0
  1037
		/// <summary>
sl@0
  1038
		/// Request to get an Input report retrieved using interrupt transfers.
sl@0
  1039
		/// </summary>
sl@0
  1040
		/// <param name="sender"></param>
sl@0
  1041
		/// <param name="e"></param>
sl@2
  1042
		///
sl@0
  1043
		private void cmdGetInputReportInterrupt_Click(object sender, EventArgs e)
sl@0
  1044
		{
sl@0
  1045
			try
sl@0
  1046
			{
sl@0
  1047
				if (_transferInProgress)
sl@0
  1048
				{
sl@0
  1049
					DisplayTransferInProgressMessage();
sl@0
  1050
				}
sl@0
  1051
				else
sl@0
  1052
				{
sl@0
  1053
					//  Don't allow another transfer request until this one completes.
sl@2
  1054
					//  Move the focus away from the button to prevent the focus from
sl@0
  1055
					//  switching to the next control in the tab order on disabling the button.
sl@0
  1056
sl@0
  1057
					fraInterruptTransfers.Focus();
sl@0
  1058
					cmdGetInputReportInterrupt.Enabled = false;
sl@0
  1059
					_transferType = TransferTypes.Interrupt;
sl@0
  1060
					RequestToGetInputReport();
sl@0
  1061
				}
sl@0
  1062
			}
sl@0
  1063
			catch (Exception ex)
sl@0
  1064
			{
sl@0
  1065
				DisplayException(Name, ex);
sl@0
  1066
				throw;
sl@0
  1067
			}
sl@0
  1068
		}
sl@0
  1069
sl@0
  1070
		///  <summary>
sl@0
  1071
		///  Set the number of Input reports the HID driver will store.
sl@0
  1072
		///  </summary>
sl@0
  1073
sl@0
  1074
		private void cmdInputReportBufferSize_Click(Object sender, EventArgs e)
sl@0
  1075
		{
sl@0
  1076
			try
sl@0
  1077
			{
sl@0
  1078
				if (_transferInProgress)
sl@0
  1079
				{
sl@0
  1080
					DisplayTransferInProgressMessage();
sl@0
  1081
				}
sl@0
  1082
				else
sl@0
  1083
				{
sl@0
  1084
					SetInputReportBufferSize();
sl@0
  1085
				}
sl@0
  1086
			}
sl@0
  1087
			catch
sl@0
  1088
				(Exception ex)
sl@0
  1089
			{
sl@0
  1090
				DisplayException(Name, ex);
sl@0
  1091
				throw;
sl@0
  1092
			}
sl@0
  1093
		}
sl@0
  1094
sl@0
  1095
		/// <summary>
sl@0
  1096
		/// Alternate sending and getting a report.
sl@0
  1097
		/// </summary>
sl@0
  1098
		/// <param name="sender"></param>
sl@0
  1099
		/// <param name="e"></param>
sl@0
  1100
sl@0
  1101
		private void cmdPeriodicTransfers_Click(object sender, EventArgs e)
sl@0
  1102
		{
sl@0
  1103
			try
sl@0
  1104
			{
sl@0
  1105
				if (cmdPeriodicTransfers.Text == "Start")
sl@0
  1106
				{
sl@0
  1107
					if (_transferInProgress)
sl@0
  1108
					{
sl@0
  1109
						DisplayTransferInProgressMessage();
sl@0
  1110
					}
sl@0
  1111
					else
sl@0
  1112
					{
sl@0
  1113
						_sendOrGet = SendOrGet.Send;
sl@0
  1114
						PeriodicTransfersStart();
sl@0
  1115
					}
sl@0
  1116
				}
sl@0
  1117
				else
sl@0
  1118
				{
sl@0
  1119
					PeriodicTransfersStop();
sl@0
  1120
				}
sl@0
  1121
			}
sl@0
  1122
			catch (Exception ex)
sl@0
  1123
			{
sl@0
  1124
				DisplayException(Name, ex);
sl@0
  1125
				throw;
sl@0
  1126
			}
sl@0
  1127
		}
sl@0
  1128
sl@0
  1129
		/// <summary>
sl@0
  1130
		/// Request to send a Feature report using a control transfer.
sl@0
  1131
		/// </summary>
sl@0
  1132
		/// <param name="sender"></param>
sl@0
  1133
		/// <param name="e"></param>
sl@0
  1134
sl@0
  1135
		private void cmdSendFeatureReport_Click(object sender, EventArgs e)
sl@0
  1136
		{
sl@0
  1137
			try
sl@0
  1138
			{
sl@0
  1139
				if (_transferInProgress)
sl@0
  1140
				{
sl@0
  1141
					DisplayTransferInProgressMessage();
sl@0
  1142
				}
sl@0
  1143
				else
sl@0
  1144
				{
sl@0
  1145
					//  Don't allow another transfer request until this one completes.
sl@2
  1146
					//  Move the focus away from the button to prevent the focus from
sl@0
  1147
					//  switching to the next control in the tab order on disabling the button.
sl@0
  1148
sl@0
  1149
					fraControlTransfers.Focus();
sl@0
  1150
					cmdSendFeatureReport.Enabled = false;
sl@0
  1151
					_transferType = TransferTypes.Control;
sl@0
  1152
					RequestToSendFeatureReport();
sl@0
  1153
				}
sl@0
  1154
			}
sl@0
  1155
			catch (Exception ex)
sl@0
  1156
			{
sl@0
  1157
				DisplayException(Name, ex);
sl@0
  1158
				throw;
sl@0
  1159
			}
sl@0
  1160
		}
sl@0
  1161
sl@0
  1162
		/// <summary>
sl@0
  1163
		/// Request to send an Output report using a control transfer.
sl@0
  1164
		/// </summary>
sl@0
  1165
		/// <param name="sender"></param>
sl@0
  1166
		/// <param name="e"></param>
sl@2
  1167
		///
sl@0
  1168
		private void cmdSendOutputReportControl_Click(object sender, EventArgs e)
sl@0
  1169
		{
sl@0
  1170
			try
sl@0
  1171
			{
sl@0
  1172
				if (_transferInProgress)
sl@0
  1173
				{
sl@0
  1174
					DisplayTransferInProgressMessage();
sl@0
  1175
				}
sl@0
  1176
				else
sl@0
  1177
				{
sl@0
  1178
					//  Don't allow another transfer request until this one completes.
sl@2
  1179
					//  Move the focus away from the button to prevent the focus from
sl@0
  1180
					//  switching to the next control in the tab order on disabling the button.
sl@0
  1181
sl@0
  1182
					fraControlTransfers.Focus();
sl@0
  1183
					cmdSendOutputReportControl.Enabled = false;
sl@0
  1184
					_transferType = TransferTypes.Control;
sl@0
  1185
					RequestToSendOutputReport();
sl@0
  1186
				}
sl@0
  1187
			}
sl@0
  1188
			catch (Exception ex)
sl@0
  1189
			{
sl@0
  1190
				DisplayException(Name, ex);
sl@0
  1191
				throw;
sl@0
  1192
			}
sl@0
  1193
		}
sl@0
  1194
sl@0
  1195
		/// <summary>
sl@2
  1196
		/// Request to send an Output report using an interrupt transfer.
sl@0
  1197
		/// </summary>
sl@0
  1198
		/// <param name="sender"></param>
sl@0
  1199
		/// <param name="e"></param>
sl@0
  1200
sl@0
  1201
		private void cmdSendOutputReportInterrupt_Click(object sender, EventArgs e)
sl@0
  1202
		{
sl@0
  1203
			try
sl@0
  1204
			{
sl@0
  1205
				if (_transferInProgress)
sl@0
  1206
				{
sl@0
  1207
					DisplayTransferInProgressMessage();
sl@0
  1208
				}
sl@0
  1209
				else
sl@0
  1210
				{
sl@0
  1211
					//  Don't allow another transfer request until this one completes.
sl@2
  1212
					//  Move the focus away from the button to prevent the focus from
sl@0
  1213
					//  switching to the next control in the tab order on disabling the button.
sl@0
  1214
sl@0
  1215
					fraInterruptTransfers.Focus();
sl@0
  1216
					cmdSendOutputReportInterrupt.Enabled = false;
sl@0
  1217
					_transferType = TransferTypes.Interrupt;
sl@0
  1218
					RequestToSendOutputReport();
sl@0
  1219
				}
sl@0
  1220
			}
sl@0
  1221
			catch (Exception ex)
sl@0
  1222
			{
sl@0
  1223
				DisplayException(Name, ex);
sl@0
  1224
				throw;
sl@0
  1225
			}
sl@0
  1226
		}
sl@0
  1227
sl@0
  1228
		///  <summary>
sl@0
  1229
		///  Called on arrival of any device.
sl@0
  1230
		///  Calls a routine that searches to see if the desired device is present.
sl@0
  1231
		///  </summary>
sl@0
  1232
sl@0
  1233
		private void DeviceAdded(object sender, EventArrivedEventArgs e)
sl@0
  1234
		{
sl@0
  1235
			try
sl@0
  1236
			{
sl@0
  1237
				Debug.WriteLine("A USB device has been inserted");
sl@0
  1238
sl@0
  1239
				_deviceDetected = FindDeviceUsingWmi();
sl@0
  1240
			}
sl@0
  1241
			catch (Exception ex)
sl@0
  1242
			{
sl@0
  1243
				DisplayException(Name, ex);
sl@0
  1244
				throw;
sl@0
  1245
			}
sl@0
  1246
		}
sl@0
  1247
sl@0
  1248
		///  <summary>
sl@0
  1249
		///  Called if the user changes the Vendor ID or Product ID in the text box.
sl@0
  1250
		///  </summary>
sl@0
  1251
sl@0
  1252
		private void DeviceHasChanged()
sl@0
  1253
		{
sl@0
  1254
			try
sl@0
  1255
			{
sl@0
  1256
				//  If a device was previously detected, stop receiving notifications about it.
sl@0
  1257
sl@0
  1258
				if (_deviceHandleObtained)
sl@0
  1259
				{
sl@0
  1260
					DeviceNotificationsStop();
sl@0
  1261
sl@0
  1262
					CloseCommunications();
sl@0
  1263
				}
sl@0
  1264
				// Look for a device that matches the Vendor ID and Product ID in the text boxes.
sl@0
  1265
sl@0
  1266
				FindTheHid();
sl@0
  1267
			}
sl@0
  1268
			catch (Exception ex)
sl@0
  1269
			{
sl@0
  1270
				DisplayException(Name, ex);
sl@0
  1271
				throw;
sl@0
  1272
			}
sl@0
  1273
		}
sl@0
  1274
sl@0
  1275
		///  <summary>
sl@0
  1276
		///  Add handlers to detect device arrival and removal.
sl@0
  1277
		///  </summary>
sl@0
  1278
sl@0
  1279
		private void DeviceNotificationsStart()
sl@0
  1280
		{
sl@0
  1281
			AddDeviceArrivedHandler();
sl@0
  1282
			AddDeviceRemovedHandler();
sl@0
  1283
		}
sl@0
  1284
sl@0
  1285
		///  <summary>
sl@0
  1286
		///  Stop receiving notifications about device arrival and removal
sl@0
  1287
		///  </summary>
sl@0
  1288
sl@0
  1289
		private void DeviceNotificationsStop()
sl@0
  1290
		{
sl@0
  1291
			try
sl@0
  1292
			{
sl@0
  1293
				if (_deviceArrivedWatcher != null)
sl@0
  1294
					_deviceArrivedWatcher.Stop();
sl@0
  1295
				if (_deviceRemovedWatcher != null)
sl@0
  1296
					_deviceRemovedWatcher.Stop();
sl@0
  1297
			}
sl@0
  1298
			catch (Exception ex)
sl@0
  1299
			{
sl@0
  1300
				DisplayException(Name, ex);
sl@0
  1301
				throw;
sl@0
  1302
			}
sl@0
  1303
		}
sl@0
  1304
sl@0
  1305
		///  <summary>
sl@0
  1306
		///  Called on removal of any device.
sl@0
  1307
		///  Calls a routine that searches to see if the desired device is still present.
sl@0
  1308
		///  </summary>
sl@2
  1309
		///
sl@0
  1310
		private void DeviceRemoved(object sender, EventArgs e)
sl@0
  1311
		{
sl@0
  1312
			try
sl@0
  1313
			{
sl@0
  1314
				Debug.WriteLine("A USB device has been removed");
sl@0
  1315
sl@0
  1316
				_deviceDetected = FindDeviceUsingWmi();
sl@0
  1317
sl@0
  1318
				if (!_deviceDetected)
sl@0
  1319
				{
sl@0
  1320
					_deviceHandleObtained = false;
sl@0
  1321
					CloseCommunications();
sl@0
  1322
				}
sl@0
  1323
			}
sl@0
  1324
			catch (Exception ex)
sl@0
  1325
			{
sl@0
  1326
				DisplayException(Name, ex);
sl@0
  1327
				throw;
sl@0
  1328
			}
sl@0
  1329
		}
sl@0
  1330
sl@0
  1331
		///  <summary>
sl@0
  1332
		///  Displays received or written report data.
sl@0
  1333
		///  </summary>
sl@2
  1334
		///
sl@2
  1335
		///  <param name="buffer"> contains the report data. </param>
sl@0
  1336
		///  <param name="currentReportType" > "Input", "Output", or "Feature"</param>
sl@0
  1337
		///  <param name="currentReadOrWritten" > "read" for Input and IN Feature reports, "written" for Output and OUT Feature reports.</param>
sl@0
  1338
sl@0
  1339
		private void DisplayReportData(Byte[] buffer, ReportTypes currentReportType, ReportReadOrWritten currentReadOrWritten)
sl@0
  1340
		{
sl@0
  1341
			try
sl@0
  1342
			{
sl@0
  1343
				Int32 count;
sl@0
  1344
sl@0
  1345
				LstResults.Items.Add(currentReportType.ToString() + " report has been " + currentReadOrWritten.ToString().ToLower() + ".");
sl@0
  1346
sl@0
  1347
				//  Display the report data received in the form's list box.
sl@0
  1348
sl@0
  1349
				LstResults.Items.Add(" Report ID: " + String.Format("{0:X2} ", buffer[0]));
sl@0
  1350
				LstResults.Items.Add(" Report Data:");
sl@0
  1351
sl@0
  1352
				TxtBytesReceived.Text = "";
sl@0
  1353
sl@0
  1354
				for (count = 1; count <= buffer.Length - 1; count++)
sl@0
  1355
				{
sl@0
  1356
					//  Display bytes as 2-character Hex strings.
sl@0
  1357
sl@0
  1358
					String byteValue = String.Format("{0:X2} ", buffer[count]);
sl@0
  1359
sl@0
  1360
					LstResults.Items.Add(" " + byteValue);
sl@0
  1361
sl@0
  1362
					//  Display the received bytes in the text box.
sl@0
  1363
sl@0
  1364
					TxtBytesReceived.SelectionStart = TxtBytesReceived.Text.Length;
sl@0
  1365
					TxtBytesReceived.SelectedText = byteValue + Environment.NewLine;
sl@0
  1366
				}
sl@0
  1367
				ScrollToBottomOfListBox();
sl@0
  1368
			}
sl@0
  1369
			catch (Exception ex)
sl@0
  1370
			{
sl@0
  1371
				DisplayException(Name, ex);
sl@0
  1372
				throw;
sl@0
  1373
			}
sl@0
  1374
		}
sl@0
  1375
sl@0
  1376
		///  <summary>
sl@0
  1377
		///  Display a message if the user clicks a button when a transfer is in progress.
sl@0
  1378
		///  </summary>
sl@2
  1379
		///
sl@0
  1380
		private void DisplayTransferInProgressMessage()
sl@0
  1381
		{
sl@0
  1382
			AccessForm(FormActions.AddItemToListBox, "Command not executed because a transfer is in progress.");
sl@0
  1383
			ScrollToBottomOfListBox();
sl@0
  1384
		}
sl@0
  1385
sl@0
  1386
		///  <summary>
sl@0
  1387
		///  Do periodic transfers.
sl@0
  1388
		///  </summary>
sl@0
  1389
		/// <param name="source"></param>
sl@0
  1390
		/// <param name="e"></param>
sl@0
  1391
		///  <remarks>
sl@0
  1392
		///  The timer is enabled only if continuous (periodic) transfers have been requested.
sl@2
  1393
		///  </remarks>
sl@0
  1394
sl@0
  1395
		private void DoPeriodicTransfers(object source, ElapsedEventArgs e)
sl@0
  1396
		{
sl@0
  1397
			try
sl@0
  1398
			{
sl@0
  1399
				PeriodicTransfers();
sl@0
  1400
			}
sl@0
  1401
			catch (Exception ex)
sl@0
  1402
			{
sl@0
  1403
				DisplayException(Name, ex);
sl@0
  1404
				throw;
sl@0
  1405
			}
sl@0
  1406
		}
sl@0
  1407
sl@0
  1408
		/// <summary>
sl@0
  1409
		/// Enable the command buttons on the form.
sl@0
  1410
		/// Needed after attempting a transfer and device not found.
sl@0
  1411
		/// </summary>
sl@2
  1412
		///
sl@0
  1413
		private void EnableFormControls()
sl@0
  1414
		{
sl@0
  1415
			cmdGetInputReportInterrupt.Enabled = true;
sl@0
  1416
			cmdSendOutputReportControl.Enabled = true;
sl@0
  1417
			cmdGetInputReportControl.Enabled = true;
sl@0
  1418
			cmdGetFeatureReport.Enabled = true;
sl@0
  1419
			cmdSendFeatureReport.Enabled = true;
sl@0
  1420
			cmdPeriodicTransfers.Enabled = true;
sl@0
  1421
			cmdSendOutputReportInterrupt.Enabled = true;
sl@0
  1422
		}
sl@0
  1423
sl@0
  1424
		///  <summary>
sl@0
  1425
		///  Use the System.Management class to find a device by Vendor ID and Product ID using WMI. If found, display device properties.
sl@0
  1426
		///  </summary>
sl@2
  1427
		/// <remarks>
sl@0
  1428
		/// During debugging, if you stop the firmware but leave the device attached, the device may still be detected as present
sl@2
  1429
		/// but will be unable to communicate. The device will show up in Windows Device Manager as well.
sl@0
  1430
		/// This situation is unlikely to occur with a final product.
sl@0
  1431
		/// </remarks>
sl@0
  1432
sl@0
  1433
		private Boolean FindDeviceUsingWmi()
sl@0
  1434
		{
sl@0
  1435
			try
sl@0
  1436
			{
sl@3
  1437
                MyMarshalDataToForm(FormActions.ResetDeviceTreeView);
sl@0
  1438
				// Prepend "@" to string below to treat backslash as a normal character (not escape character):
sl@0
  1439
sl@0
  1440
				String deviceIdString = @"USB\VID_" + _myVendorId.ToString("X4") + "&PID_" + _myProductId.ToString("X4");
sl@0
  1441
sl@0
  1442
				_deviceDetected = false;
sl@0
  1443
				var searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PnPEntity");
sl@2
  1444
                int usbDeviceCounter = 0;
sl@0
  1445
sl@0
  1446
				foreach (ManagementObject queryObj in searcher.Get())
sl@0
  1447
				{
sl@2
  1448
                    string deviceId = queryObj["PNPDeviceID"].ToString();
sl@2
  1449
                    if (deviceId.Contains(deviceIdString))
sl@2
  1450
                    {
sl@2
  1451
                        _deviceDetected = true;
sl@2
  1452
                        MyMarshalDataToForm(FormActions.AddItemToListBox, "My device found (WMI):");
sl@0
  1453
sl@3
  1454
                        MyMarshalDataToForm(FormActions.AddItemToListBox, "--------");
sl@3
  1455
                        List<string> device = new List<string>();
sl@3
  1456
                        device.Add(deviceId);
sl@3
  1457
                        usbDeviceCounter++;
sl@2
  1458
                        // Display device properties.
sl@2
  1459
                        foreach (WmiDeviceProperties wmiDeviceProperty in Enum.GetValues(typeof(WmiDeviceProperties)))
sl@2
  1460
                        {
sl@2
  1461
                            MyMarshalDataToForm(FormActions.AddItemToListBox, (wmiDeviceProperty.ToString() + ": " + queryObj[wmiDeviceProperty.ToString()]));
sl@3
  1462
                            device.Add((wmiDeviceProperty.ToString() + ": " + queryObj[wmiDeviceProperty.ToString()]));
sl@2
  1463
                            Debug.WriteLine(wmiDeviceProperty.ToString() + ": {0}", queryObj[wmiDeviceProperty.ToString()]);
sl@2
  1464
                        }
sl@2
  1465
                        MyMarshalDataToForm(FormActions.AddItemToListBox, "--------");
sl@2
  1466
                        MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
sl@3
  1467
sl@3
  1468
                        MyMarshalDataToForm(FormActions.AddDeviceToTreeView, device.ToArray());
sl@3
  1469
                        MyMarshalDataToForm(FormActions.SelectDeviceInTreeView, deviceId);
sl@3
  1470
sl@2
  1471
                    }
sl@3
  1472
                    else if (deviceId.StartsWith("USB\\VID"))
sl@2
  1473
                    {
sl@3
  1474
                        List<string> device = new List<string>();
sl@3
  1475
                        device.Add(deviceId);
sl@2
  1476
                        usbDeviceCounter++;
sl@3
  1477
                        // Add device properties.
sl@2
  1478
                        foreach (WmiDeviceProperties wmiDeviceProperty in Enum.GetValues(typeof(WmiDeviceProperties)))
sl@2
  1479
                        {
sl@3
  1480
                            device.Add((wmiDeviceProperty.ToString() + ": " + queryObj[wmiDeviceProperty.ToString()]));
sl@2
  1481
                            Debug.WriteLine(wmiDeviceProperty.ToString() + ": {0}", queryObj[wmiDeviceProperty.ToString()]);
sl@2
  1482
                        }
sl@3
  1483
sl@3
  1484
                        MyMarshalDataToForm(FormActions.AddDeviceToTreeView, device.ToArray());
sl@2
  1485
                    }
sl@0
  1486
				}
sl@2
  1487
sl@4
  1488
                //Complete our device TreeView
sl@4
  1489
                MyMarshalDataToForm(FormActions.CompleteDeviceTreeView);
sl@4
  1490
sl@4
  1491
sl@2
  1492
                MyMarshalDataToForm(FormActions.AddItemToListBox, "Found " + usbDeviceCounter /*searcher.Get().Count*/ + " USB HID devices");
sl@2
  1493
sl@0
  1494
				if (!_deviceDetected)
sl@0
  1495
				{
sl@0
  1496
					MyMarshalDataToForm(FormActions.AddItemToListBox, "My device not found (WMI)");
sl@0
  1497
					MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
sl@0
  1498
				}
sl@0
  1499
				return _deviceDetected;
sl@0
  1500
			}
sl@0
  1501
			catch (Exception ex)
sl@0
  1502
			{
sl@0
  1503
				DisplayException(Name, ex);
sl@0
  1504
				throw;
sl@0
  1505
			}
sl@0
  1506
		}
sl@0
  1507
sl@0
  1508
		///  <summary>
sl@0
  1509
		///  Call HID functions that use Win32 API functions to locate a HID-class device
sl@0
  1510
		///  by its Vendor ID and Product ID. Open a handle to the device.
sl@0
  1511
		///  </summary>
sl@2
  1512
		///
sl@0
  1513
		///  <returns>
sl@0
  1514
		///   True if the device is detected, False if not detected.
sl@0
  1515
		///  </returns>
sl@0
  1516
sl@0
  1517
		private Boolean FindTheHid()
sl@0
  1518
		{
sl@0
  1519
			var devicePathName = new String[128];
sl@0
  1520
			String myDevicePathName = "";
sl@0
  1521
sl@0
  1522
			try
sl@0
  1523
			{
sl@0
  1524
				_deviceHandleObtained = false;
sl@0
  1525
				CloseCommunications();
sl@0
  1526
sl@0
  1527
				//  Get the device's Vendor ID and Product ID from the form's text boxes.
sl@0
  1528
sl@0
  1529
				GetVendorAndProductIDsFromTextBoxes(ref _myVendorId, ref _myProductId);
sl@0
  1530
sl@0
  1531
				// Get the HID-class GUID.
sl@0
  1532
sl@0
  1533
				Guid hidGuid = _myHid.GetHidGuid();
sl@0
  1534
sl@0
  1535
				String functionName = "GetHidGuid";
sl@0
  1536
				Debug.WriteLine(_myDebugging.ResultOfApiCall(functionName));
sl@0
  1537
				Debug.WriteLine("  GUID for system HIDs: " + hidGuid.ToString());
sl@0
  1538
sl@0
  1539
				//  Fill an array with the device path names of all attached HIDs.
sl@0
  1540
sl@0
  1541
				Boolean availableHids = _myDeviceManagement.FindDeviceFromGuid(hidGuid, ref devicePathName);
sl@0
  1542
sl@0
  1543
				//  If there is at least one HID, attempt to read the Vendor ID and Product ID
sl@0
  1544
				//  of each device until there is a match or all devices have been examined.
sl@0
  1545
sl@0
  1546
				if (availableHids)
sl@0
  1547
				{
sl@0
  1548
					Int32 memberIndex = 0;
sl@0
  1549
sl@0
  1550
					do
sl@0
  1551
					{
sl@0
  1552
						// Open the handle without read/write access to enable getting information about any HID, even system keyboards and mice.
sl@0
  1553
sl@0
  1554
						_hidHandle = _myHid.OpenHandle(devicePathName[memberIndex], false);
sl@0
  1555
sl@0
  1556
						functionName = "CreateFile";
sl@0
  1557
						Debug.WriteLine(_myDebugging.ResultOfApiCall(functionName));
sl@0
  1558
						Debug.WriteLine("  Returned handle: " + _hidHandle);
sl@0
  1559
sl@0
  1560
						if (!_hidHandle.IsInvalid)
sl@0
  1561
						{
sl@2
  1562
							// The returned handle is valid,
sl@0
  1563
							// so find out if this is the device we're looking for.
sl@0
  1564
sl@0
  1565
							_myHid.DeviceAttributes.Size = Marshal.SizeOf(_myHid.DeviceAttributes);
sl@0
  1566
sl@0
  1567
							Boolean success = _myHid.GetAttributes(_hidHandle, ref _myHid.DeviceAttributes);
sl@0
  1568
sl@0
  1569
							if (success)
sl@0
  1570
							{
sl@0
  1571
								Debug.WriteLine("  HIDD_ATTRIBUTES structure filled without error.");
sl@0
  1572
								Debug.WriteLine("  Structure size: " + _myHid.DeviceAttributes.Size);
sl@0
  1573
								Debug.WriteLine("  Vendor ID: " + Convert.ToString(_myHid.DeviceAttributes.VendorID, 16));
sl@0
  1574
								Debug.WriteLine("  Product ID: " + Convert.ToString(_myHid.DeviceAttributes.ProductID, 16));
sl@0
  1575
								Debug.WriteLine("  Version Number: " + Convert.ToString(_myHid.DeviceAttributes.VersionNumber, 16));
sl@0
  1576
sl@0
  1577
								if ((_myHid.DeviceAttributes.VendorID == _myVendorId) && (_myHid.DeviceAttributes.ProductID == _myProductId))
sl@0
  1578
								{
sl@0
  1579
									Debug.WriteLine("  Handle obtained to my device");
sl@0
  1580
sl@0
  1581
									//  Display the information in form's list box.
sl@0
  1582
sl@0
  1583
									MyMarshalDataToForm(FormActions.AddItemToListBox, "Handle obtained to my device:");
sl@0
  1584
									MyMarshalDataToForm(FormActions.AddItemToListBox, "  Vendor ID= " + Convert.ToString(_myHid.DeviceAttributes.VendorID, 16));
sl@0
  1585
									MyMarshalDataToForm(FormActions.AddItemToListBox, "  Product ID = " + Convert.ToString(_myHid.DeviceAttributes.ProductID, 16));
sl@0
  1586
									MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
sl@0
  1587
sl@0
  1588
									_deviceHandleObtained = true;
sl@0
  1589
sl@0
  1590
									myDevicePathName = devicePathName[memberIndex];
sl@0
  1591
								}
sl@0
  1592
								else
sl@0
  1593
								{
sl@0
  1594
									//  It's not a match, so close the handle.
sl@0
  1595
sl@0
  1596
									_deviceHandleObtained = false;
sl@0
  1597
									_hidHandle.Close();
sl@0
  1598
								}
sl@0
  1599
							}
sl@0
  1600
							else
sl@0
  1601
							{
sl@0
  1602
								//  There was a problem retrieving the information.
sl@0
  1603
sl@0
  1604
								Debug.WriteLine("  Error in filling HIDD_ATTRIBUTES structure.");
sl@0
  1605
								_deviceHandleObtained = false;
sl@0
  1606
								_hidHandle.Close();
sl@0
  1607
							}
sl@0
  1608
						}
sl@0
  1609
sl@0
  1610
						//  Keep looking until we find the device or there are no devices left to examine.
sl@0
  1611
sl@0
  1612
						memberIndex = memberIndex + 1;
sl@0
  1613
					}
sl@0
  1614
					while (!((_deviceHandleObtained || (memberIndex == devicePathName.Length))));
sl@0
  1615
				}
sl@0
  1616
sl@0
  1617
				if (_deviceHandleObtained)
sl@0
  1618
				{
sl@0
  1619
					//  The device was detected.
sl@0
  1620
					//  Learn the capabilities of the device.
sl@0
  1621
sl@0
  1622
					_myHid.Capabilities = _myHid.GetDeviceCapabilities(_hidHandle);
sl@0
  1623
sl@0
  1624
					//  Find out if the device is a system mouse or keyboard.
sl@0
  1625
sl@0
  1626
					_hidUsage = _myHid.GetHidUsage(_myHid.Capabilities);
sl@0
  1627
sl@0
  1628
					//  Get the Input report buffer size.
sl@0
  1629
sl@0
  1630
					GetInputReportBufferSize();
sl@0
  1631
					MyMarshalDataToForm(FormActions.EnableInputReportBufferSize, "");
sl@0
  1632
sl@0
  1633
					//Close the handle and reopen it with read/write access.
sl@0
  1634
sl@0
  1635
					_hidHandle.Close();
sl@0
  1636
sl@0
  1637
					_hidHandle = _myHid.OpenHandle(myDevicePathName, true);
sl@0
  1638
sl@0
  1639
					if (_hidHandle.IsInvalid)
sl@0
  1640
					{
sl@0
  1641
						MyMarshalDataToForm(FormActions.AddItemToListBox, "The device is a system " + _hidUsage + ".");
sl@0
  1642
						MyMarshalDataToForm(FormActions.AddItemToListBox, "Windows 2000 and later obtain exclusive access to Input and Output reports for this devices.");
sl@0
  1643
						MyMarshalDataToForm(FormActions.AddItemToListBox, "Windows 8 also obtains exclusive access to Feature reports.");
sl@0
  1644
						MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
sl@0
  1645
					}
sl@0
  1646
					else
sl@0
  1647
					{
sl@0
  1648
						if (_myHid.Capabilities.InputReportByteLength > 0)
sl@0
  1649
						{
sl@2
  1650
							//  Set the size of the Input report buffer.
sl@0
  1651
sl@0
  1652
							var inputReportBuffer = new Byte[_myHid.Capabilities.InputReportByteLength];
sl@0
  1653
sl@0
  1654
							_deviceData = new FileStream(_hidHandle, FileAccess.Read | FileAccess.Write, inputReportBuffer.Length, false);
sl@0
  1655
						}
sl@0
  1656
sl@0
  1657
						if (_myHid.Capabilities.OutputReportByteLength > 0)
sl@0
  1658
						{
sl@0
  1659
							Byte[] outputReportBuffer = null;
sl@0
  1660
						}
sl@0
  1661
						//  Flush any waiting reports in the input buffer. (optional)
sl@0
  1662
sl@0
  1663
						_myHid.FlushQueue(_hidHandle);
sl@0
  1664
					}
sl@0
  1665
				}
sl@0
  1666
				else
sl@0
  1667
				{
sl@0
  1668
					MyMarshalDataToForm(FormActions.AddItemToListBox, "Device not found.");
sl@0
  1669
					MyMarshalDataToForm(FormActions.DisableInputReportBufferSize, "");
sl@0
  1670
					EnableFormControls();
sl@0
  1671
					MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
sl@0
  1672
				}
sl@0
  1673
				return _deviceHandleObtained;
sl@0
  1674
			}
sl@0
  1675
			catch (Exception ex)
sl@0
  1676
			{
sl@0
  1677
				DisplayException(Name, ex);
sl@0
  1678
				throw;
sl@0
  1679
			}
sl@0
  1680
		}
sl@0
  1681
sl@0
  1682
		///  <summary>
sl@0
  1683
		///  Perform shutdown operations.
sl@0
  1684
		///  </summary>
sl@0
  1685
sl@0
  1686
		private void frmMain_Closed(Object eventSender, EventArgs eventArgs)
sl@0
  1687
		{
sl@0
  1688
			try
sl@0
  1689
			{
sl@0
  1690
				Shutdown();
sl@0
  1691
			}
sl@0
  1692
			catch (Exception ex)
sl@0
  1693
			{
sl@0
  1694
				DisplayException(Name, ex);
sl@0
  1695
				throw;
sl@0
  1696
			}
sl@0
  1697
		}
sl@0
  1698
sl@0
  1699
		///  <summary>
sl@0
  1700
		///  Perform startup operations.
sl@0
  1701
		///  </summary>
sl@0
  1702
sl@0
  1703
		private void frmMain_Load(Object eventSender, EventArgs eventArgs)
sl@0
  1704
		{
sl@0
  1705
			try
sl@0
  1706
			{
sl@0
  1707
				FrmMy = this;
sl@0
  1708
				Startup();
sl@0
  1709
			}
sl@0
  1710
			catch (Exception ex)
sl@0
  1711
			{
sl@0
  1712
				DisplayException(Name, ex);
sl@0
  1713
				throw;
sl@0
  1714
			}
sl@0
  1715
		}
sl@0
  1716
sl@0
  1717
		private void GetBytesToSend()
sl@0
  1718
		{
sl@0
  1719
			try
sl@0
  1720
			{
sl@0
  1721
				//  Get the bytes to send in a report from the combo boxes.
sl@0
  1722
				//  Increment the values if the autoincrement check box is selected.
sl@0
  1723
sl@0
  1724
				if (ChkAutoincrement.Checked)
sl@0
  1725
				{
sl@0
  1726
					if (CboByte0.SelectedIndex < 255)
sl@0
  1727
					{
sl@0
  1728
						CboByte0.SelectedIndex = CboByte0.SelectedIndex + 1;
sl@0
  1729
					}
sl@0
  1730
					else
sl@0
  1731
					{
sl@0
  1732
						CboByte0.SelectedIndex = 0;
sl@0
  1733
					}
sl@0
  1734
					if (CboByte1.SelectedIndex < 255)
sl@0
  1735
					{
sl@0
  1736
						CboByte1.SelectedIndex = CboByte1.SelectedIndex + 1;
sl@0
  1737
					}
sl@0
  1738
					else
sl@0
  1739
					{
sl@0
  1740
						CboByte1.SelectedIndex = 0;
sl@0
  1741
					}
sl@0
  1742
				}
sl@0
  1743
			}
sl@0
  1744
			catch (Exception ex)
sl@0
  1745
			{
sl@0
  1746
				DisplayException(Name, ex);
sl@0
  1747
				throw;
sl@0
  1748
			}
sl@0
  1749
		}
sl@0
  1750
sl@0
  1751
		///  <summary>
sl@0
  1752
		///  Find and display the number of Input buffers
sl@2
  1753
		///  (the number of Input reports the HID driver will store).
sl@0
  1754
		///  </summary>
sl@0
  1755
sl@0
  1756
		private void GetInputReportBufferSize()
sl@0
  1757
		{
sl@0
  1758
			Int32 numberOfInputBuffers = 0;
sl@0
  1759
			Boolean success;
sl@0
  1760
sl@0
  1761
			try
sl@0
  1762
			{
sl@0
  1763
				//  Get the number of input buffers.
sl@0
  1764
sl@0
  1765
				_myHid.GetNumberOfInputBuffers(_hidHandle, ref numberOfInputBuffers);
sl@0
  1766
sl@0
  1767
				//  Display the result in the text box.
sl@0
  1768
sl@0
  1769
				MyMarshalDataToForm(FormActions.SetInputReportBufferSize, Convert.ToString(numberOfInputBuffers));
sl@0
  1770
			}
sl@0
  1771
			catch (Exception ex)
sl@0
  1772
			{
sl@0
  1773
				DisplayException(Name, ex);
sl@0
  1774
				throw;
sl@0
  1775
			}
sl@0
  1776
		}
sl@0
  1777
sl@0
  1778
		///  <summary>
sl@2
  1779
		///  Retrieve a Vendor ID and Product ID in hexadecimal
sl@0
  1780
		///  from the form's text boxes and convert the text to Int32s.
sl@0
  1781
		///  </summary>
sl@2
  1782
		///
sl@0
  1783
		///  <param name="myVendorId"> the Vendor ID</param>
sl@0
  1784
		///  <param name="myProductId"> the Product ID</param>
sl@0
  1785
sl@0
  1786
		private void GetVendorAndProductIDsFromTextBoxes(ref Int32 myVendorId, ref Int32 myProductId)
sl@0
  1787
		{
sl@0
  1788
			try
sl@0
  1789
			{
sl@0
  1790
				myVendorId = Int32.Parse(txtVendorID.Text, NumberStyles.AllowHexSpecifier);
sl@0
  1791
				myProductId = Int32.Parse(txtProductID.Text, NumberStyles.AllowHexSpecifier);
sl@0
  1792
			}
sl@0
  1793
			catch (Exception ex)
sl@0
  1794
			{
sl@0
  1795
				DisplayException(Name, ex);
sl@0
  1796
				throw;
sl@0
  1797
			}
sl@0
  1798
		}
sl@0
  1799
sl@0
  1800
		///  <summary>
sl@0
  1801
		///  Initialize the elements on the form.
sl@0
  1802
		///  </summary>
sl@0
  1803
sl@0
  1804
		private void InitializeDisplay()
sl@0
  1805
		{
sl@0
  1806
			try
sl@0
  1807
			{
sl@0
  1808
				//  Create a dropdown list box for each byte to send in a report.
sl@0
  1809
				//  Display the values as 2-character hex strings.
sl@0
  1810
sl@0
  1811
				Int16 count;
sl@0
  1812
				for (count = 0; count <= 255; count++)
sl@0
  1813
				{
sl@0
  1814
					String byteValue = String.Format("{0:X2} ", count);
sl@0
  1815
					FrmMy.CboByte0.Items.Insert(count, byteValue);
sl@0
  1816
					FrmMy.CboByte1.Items.Insert(count, byteValue);
sl@0
  1817
				}
sl@0
  1818
sl@0
  1819
				//  Select a default value for each box
sl@0
  1820
sl@0
  1821
				FrmMy.CboByte0.SelectedIndex = 0;
sl@0
  1822
				FrmMy.CboByte1.SelectedIndex = 128;
sl@0
  1823
				FrmMy.radInputOutputInterrupt.Checked = true;
sl@0
  1824
sl@0
  1825
				//  Check the autoincrement box to increment the values each time a report is sent.
sl@0
  1826
sl@0
  1827
				ChkAutoincrement.CheckState = CheckState.Checked;
sl@0
  1828
sl@0
  1829
				//  Don't allow the user to select an input report buffer size until there is
sl@0
  1830
				//  a handle to a HID.
sl@0
  1831
sl@0
  1832
				cmdInputReportBufferSize.Focus();
sl@0
  1833
				cmdInputReportBufferSize.Enabled = false;
sl@0
  1834
sl@0
  1835
				LstResults.Items.Add("For a more detailed event log, view debug statements in Visual Studio's Output window:");
sl@0
  1836
				LstResults.Items.Add("Click Build > Configuration Manager > Active Solution Configuration > Debug > Close.");
sl@0
  1837
				LstResults.Items.Add("Then click View > Output.");
sl@0
  1838
				LstResults.Items.Add("");
sl@0
  1839
			}
sl@0
  1840
			catch (Exception ex)
sl@0
  1841
			{
sl@0
  1842
				DisplayException(Name, ex);
sl@0
  1843
				throw;
sl@0
  1844
			}
sl@0
  1845
		}
sl@0
  1846
sl@0
  1847
		///  <summary>
sl@2
  1848
		///  Enables accessing a form's controls from another thread
sl@0
  1849
		///  </summary>
sl@2
  1850
		///
sl@0
  1851
		///  <param name="action"> a FormActions member that names the action to perform on the form </param>
sl@2
  1852
		///  <param name="textToDisplay"> text that the form displays or the code uses for
sl@0
  1853
		///  another purpose. Actions that don't use text ignore this parameter.  </param>
sl@0
  1854
sl@3
  1855
        private void MyMarshalDataToForm(FormActions action, params string[] strings)
sl@0
  1856
		{
sl@0
  1857
			try
sl@0
  1858
			{
sl@3
  1859
                object[] args = { action, strings };
sl@0
  1860
sl@0
  1861
				//  The AccessForm routine contains the code that accesses the form.
sl@0
  1862
sl@0
  1863
				MarshalDataToForm marshalDataToFormDelegate = AccessForm;
sl@0
  1864
sl@0
  1865
				//  Execute AccessForm, passing the parameters in args.
sl@0
  1866
sl@0
  1867
				Invoke(marshalDataToFormDelegate, args);
sl@0
  1868
			}
sl@0
  1869
			catch (Exception ex)
sl@0
  1870
			{
sl@0
  1871
				DisplayException(Name, ex);
sl@0
  1872
				throw;
sl@0
  1873
			}
sl@0
  1874
		}
sl@0
  1875
sl@0
  1876
		/// <summary>
sl@0
  1877
		/// Timeout if read via interrupt transfer doesn't return.
sl@0
  1878
		/// </summary>
sl@0
  1879
sl@0
  1880
		private void OnReadTimeout()
sl@0
  1881
		{
sl@0
  1882
			try
sl@0
  1883
			{
sl@0
  1884
				MyMarshalDataToForm(FormActions.AddItemToListBox, "The attempt to read a report timed out.");
sl@0
  1885
				MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
sl@0
  1886
				CloseCommunications();
sl@0
  1887
				MyMarshalDataToForm(FormActions.EnableGetInputReportInterruptTransfer, "");
sl@0
  1888
				_transferInProgress = false;
sl@0
  1889
				_sendOrGet = SendOrGet.Send;
sl@0
  1890
			}
sl@0
  1891
			catch (Exception ex)
sl@0
  1892
			{
sl@0
  1893
				DisplayException(Name, ex);
sl@0
  1894
				throw;
sl@0
  1895
			}
sl@0
  1896
		}
sl@0
  1897
sl@0
  1898
		/// <summary>
sl@0
  1899
		/// Timeout if write via interrupt transfer doesn't return.
sl@0
  1900
		/// </summary>
sl@0
  1901
sl@0
  1902
		private void OnWriteTimeout()
sl@0
  1903
		{
sl@0
  1904
			try
sl@0
  1905
			{
sl@0
  1906
				MyMarshalDataToForm(FormActions.AddItemToListBox, "The attempt to write a report timed out.");
sl@0
  1907
				MyMarshalDataToForm(FormActions.ScrollToBottomOfListBox, "");
sl@0
  1908
				CloseCommunications();
sl@0
  1909
				MyMarshalDataToForm(FormActions.EnableSendOutputReportInterrupt, "");
sl@0
  1910
				_transferInProgress = false;
sl@0
  1911
				_sendOrGet = SendOrGet.Get;
sl@0
  1912
			}
sl@0
  1913
			catch (Exception ex)
sl@0
  1914
			{
sl@0
  1915
				DisplayException(Name, ex);
sl@0
  1916
				throw;
sl@0
  1917
			}
sl@0
  1918
		}
sl@0
  1919
sl@0
  1920
		/// <summary>
sl@0
  1921
		/// Alternat sending and getting a report.
sl@0
  1922
		/// </summary>
sl@0
  1923
sl@0
  1924
		private void PeriodicTransfers()
sl@0
  1925
		{
sl@0
  1926
			try
sl@0
  1927
			{
sl@0
  1928
				if (!_transferInProgress)
sl@0
  1929
				{
sl@0
  1930
					if (_reportType == ReportTypes.Feature)
sl@0
  1931
					{
sl@0
  1932
						SendOrGetFeatureReport();
sl@0
  1933
					}
sl@0
  1934
					else
sl@0
  1935
					{
sl@0
  1936
						// Output and Input reports
sl@0
  1937
sl@0
  1938
						SendOutputReportOrGetInputReport();
sl@0
  1939
					}
sl@0
  1940
				}
sl@0
  1941
			}
sl@0
  1942
			catch (Exception ex)
sl@0
  1943
			{
sl@0
  1944
				DisplayException(Name, ex);
sl@0
  1945
				throw;
sl@0
  1946
			}
sl@0
  1947
		}
sl@0
  1948
sl@0
  1949
		/// <summary>
sl@0
  1950
		/// Start doing periodic transfers.
sl@0
  1951
		/// </summary>
sl@0
  1952
sl@0
  1953
		private void PeriodicTransfersStart()
sl@0
  1954
		{
sl@0
  1955
			// Don't allow changing the transfer type while transfers are in progress.
sl@0
  1956
sl@0
  1957
			if (radFeature.Checked)
sl@0
  1958
			{
sl@0
  1959
				radInputOutputControl.Enabled = false;
sl@0
  1960
				radInputOutputInterrupt.Enabled = false;
sl@0
  1961
			}
sl@0
  1962
			else if (radInputOutputControl.Checked)
sl@0
  1963
			{
sl@0
  1964
				radFeature.Enabled = false;
sl@0
  1965
				radInputOutputInterrupt.Enabled = false;
sl@0
  1966
			}
sl@0
  1967
			else if (radInputOutputInterrupt.Checked)
sl@0
  1968
			{
sl@0
  1969
				radFeature.Enabled = false;
sl@0
  1970
				radInputOutputControl.Enabled = false;
sl@0
  1971
			}
sl@0
  1972
sl@0
  1973
			//  Change the command button's text.
sl@0
  1974
sl@0
  1975
			cmdPeriodicTransfers.Text = "Stop";
sl@0
  1976
sl@0
  1977
			//  Enable the timer event to trigger a set of transfers.
sl@0
  1978
sl@0
  1979
			_periodicTransfers.Start();
sl@0
  1980
sl@0
  1981
			cmdPeriodicTransfers.Enabled = true;
sl@0
  1982
sl@0
  1983
			if (radInputOutputInterrupt.Checked)
sl@0
  1984
			{
sl@0
  1985
				_transferType = TransferTypes.Interrupt;
sl@0
  1986
				_reportType = ReportTypes.Output;
sl@0
  1987
			}
sl@0
  1988
			else if (radInputOutputControl.Checked)
sl@0
  1989
			{
sl@0
  1990
				_transferType = TransferTypes.Control;
sl@0
  1991
				_reportType = ReportTypes.Output;
sl@0
  1992
			}
sl@0
  1993
			else if (radFeature.Checked)
sl@0
  1994
			{
sl@0
  1995
				_transferType = TransferTypes.Control;
sl@0
  1996
				_reportType = ReportTypes.Feature;
sl@0
  1997
			}
sl@0
  1998
			_periodicTransfersRequested = true;
sl@0
  1999
			PeriodicTransfers();
sl@0
  2000
		}
sl@0
  2001
sl@0
  2002
		/// <summary>
sl@0
  2003
		/// Stop doing periodic transfers.
sl@0
  2004
		/// </summary>
sl@0
  2005
sl@0
  2006
		private void PeriodicTransfersStop()
sl@0
  2007
		{
sl@0
  2008
			//  Stop doing continuous transfers.
sl@0
  2009
sl@0
  2010
			_periodicTransfersRequested = false;
sl@0
  2011
sl@2
  2012
			// Disable the timer that triggers the transfers.
sl@0
  2013
sl@0
  2014
			_periodicTransfers.Stop();
sl@0
  2015
			cmdPeriodicTransfers.Enabled = true;
sl@0
  2016
sl@0
  2017
			//  Change the command button's text.
sl@0
  2018
sl@0
  2019
			cmdPeriodicTransfers.Text = "Start";
sl@0
  2020
sl@0
  2021
			// Re-allow changing the transfer type.
sl@0
  2022
sl@0
  2023
			radFeature.Enabled = true;
sl@0
  2024
			radInputOutputControl.Enabled = true;
sl@0
  2025
			radInputOutputInterrupt.Enabled = true;
sl@0
  2026
		}
sl@0
  2027
sl@0
  2028
		private void radInputOutputControl_CheckedChanged(object sender, EventArgs e)
sl@0
  2029
		{
sl@0
  2030
		}
sl@0
  2031
sl@0
  2032
		private void radInputOutputInterrupt_CheckedChanged(object sender, EventArgs e)
sl@0
  2033
		{
sl@0
  2034
		}
sl@0
  2035
sl@0
  2036
		private void radFeature_CheckedChanged(object sender, EventArgs e)
sl@0
  2037
		{
sl@0
  2038
		}
sl@0
  2039
sl@0
  2040
		///  <summary>
sl@0
  2041
		///  Request a Feature report.
sl@0
  2042
		///  Assumes report ID = 0.
sl@0
  2043
		///  </summary>
sl@0
  2044
sl@0
  2045
		private void RequestToGetFeatureReport()
sl@0
  2046
		{
sl@0
  2047
			String byteValue = null;
sl@0
  2048
sl@0
  2049
			try
sl@0
  2050
			{
sl@0
  2051
				//  If the device hasn't been detected, was removed, or timed out on a previous attempt
sl@0
  2052
				//  to access it, look for the device.
sl@0
  2053
sl@0
  2054
				if (!_deviceHandleObtained)
sl@0
  2055
				{
sl@0
  2056
					_deviceHandleObtained = FindTheHid();
sl@0
  2057
				}
sl@0
  2058
sl@0
  2059
				if (_deviceHandleObtained)
sl@0
  2060
				{
sl@0
  2061
					Byte[] inFeatureReportBuffer = null;
sl@0
  2062
sl@0
  2063
					if ((_myHid.Capabilities.FeatureReportByteLength > 0))
sl@0
  2064
					{
sl@2
  2065
						//  The HID has a Feature report.
sl@0
  2066
						//  Read a report from the device.
sl@0
  2067
sl@2
  2068
						//  Set the size of the Feature report buffer.
sl@0
  2069
sl@0
  2070
						if ((_myHid.Capabilities.FeatureReportByteLength > 0))
sl@0
  2071
						{
sl@0
  2072
							inFeatureReportBuffer = new Byte[_myHid.Capabilities.FeatureReportByteLength];
sl@0
  2073
						}
sl@0
  2074
sl@0
  2075
						//  Read a report.
sl@0
  2076
sl@0
  2077
						Boolean success = _myHid.GetFeatureReport(_hidHandle, ref inFeatureReportBuffer);
sl@0
  2078
sl@0
  2079
						if (success)
sl@0
  2080
						{
sl@0
  2081
							DisplayReportData(inFeatureReportBuffer, ReportTypes.Feature, ReportReadOrWritten.Read);
sl@0
  2082
						}
sl@0
  2083
						else
sl@0
  2084
						{
sl@0
  2085
							CloseCommunications();
sl@0
  2086
							MyMarshalDataToForm(FormActions.AddItemToListBox, "The attempt to read a Feature report failed.");
sl@0
  2087
							ScrollToBottomOfListBox();
sl@0
  2088
						}
sl@0
  2089
					}
sl@0
  2090
					else
sl@0
  2091
					{
sl@0
  2092
						MyMarshalDataToForm(FormActions.AddItemToListBox, "The HID doesn't have a Feature report.");
sl@0
  2093
						ScrollToBottomOfListBox();
sl@0
  2094
					}
sl@0
  2095
				}
sl@0
  2096
				_transferInProgress = false;
sl@0
  2097
				cmdGetFeatureReport.Enabled = true;
sl@0
  2098
			}
sl@0
  2099
			catch (Exception ex)
sl@0
  2100
			{
sl@0
  2101
				DisplayException(Name, ex);
sl@0
  2102
				throw;
sl@0
  2103
			}
sl@0
  2104
		}
sl@0
  2105
sl@0
  2106
		///  <summary>
sl@0
  2107
		///  Request an Input report.
sl@0
  2108
		///  Assumes report ID = 0.
sl@0
  2109
		///  </summary>
sl@0
  2110
sl@0
  2111
		private async void RequestToGetInputReport()
sl@0
  2112
		{
sl@0
  2113
			const Int32 readTimeout = 5000;
sl@0
  2114
sl@0
  2115
			String byteValue = null;
sl@0
  2116
			Byte[] inputReportBuffer = null;
sl@0
  2117
sl@0
  2118
			try
sl@0
  2119
			{
sl@0
  2120
				Boolean success = false;
sl@0
  2121
sl@0
  2122
				//  If the device hasn't been detected, was removed, or timed out on a previous attempt
sl@0
  2123
				//  to access it, look for the device.
sl@0
  2124
sl@0
  2125
				if (!_deviceHandleObtained)
sl@0
  2126
				{
sl@0
  2127
					_deviceHandleObtained = FindTheHid();
sl@0
  2128
				}
sl@0
  2129
sl@0
  2130
				if (_deviceHandleObtained)
sl@0
  2131
				{
sl@0
  2132
					//  Don't attempt to exchange reports if valid handles aren't available
sl@0
  2133
					//  (as for a mouse or keyboard under Windows 2000 and later.)
sl@0
  2134
sl@0
  2135
					if (!_hidHandle.IsInvalid)
sl@0
  2136
					{
sl@0
  2137
						//  Read an Input report.
sl@0
  2138
sl@0
  2139
						//  Don't attempt to send an Input report if the HID has no Input report.
sl@0
  2140
						//  (The HID spec requires all HIDs to have an interrupt IN endpoint,
sl@0
  2141
						//  which suggests that all HIDs must support Input reports.)
sl@0
  2142
sl@0
  2143
						if (_myHid.Capabilities.InputReportByteLength > 0)
sl@0
  2144
						{
sl@2
  2145
							//  Set the size of the Input report buffer.
sl@0
  2146
sl@0
  2147
							inputReportBuffer = new Byte[_myHid.Capabilities.InputReportByteLength];
sl@0
  2148
sl@0
  2149
							if (_transferType.Equals(TransferTypes.Control))
sl@0
  2150
							{
sl@0
  2151
								{
sl@0
  2152
									_transferInProgress = true;
sl@0
  2153
sl@0
  2154
									//  Read a report using a control transfer.
sl@0
  2155
sl@0
  2156
									success = _myHid.GetInputReportViaControlTransfer(_hidHandle, ref inputReportBuffer);
sl@0
  2157
									cmdGetInputReportControl.Enabled = true;
sl@0
  2158
									_transferInProgress = false;
sl@0
  2159
								}
sl@0
  2160
							}
sl@0
  2161
							else
sl@0
  2162
							{
sl@0
  2163
								{
sl@0
  2164
									_transferInProgress = true;
sl@0
  2165
sl@2
  2166
									//  Read a report using interrupt transfers.
sl@0
  2167
									//  Timeout if no report available.
sl@2
  2168
									//  To enable reading a report without blocking the calling thread, uses Filestream's ReadAsync method.
sl@0
  2169
sl@0
  2170
									// Create a delegate to execute on a timeout.
sl@0
  2171
sl@0
  2172
									Action onReadTimeoutAction = OnReadTimeout;
sl@0
  2173
sl@0
  2174
									// The CancellationTokenSource specifies the timeout value and the action to take on a timeout.
sl@0
  2175
sl@0
  2176
									var cts = new CancellationTokenSource();
sl@0
  2177
sl@0
  2178
									// Cancel the read if it hasn't completed after a timeout.
sl@0
  2179
sl@0
  2180
									cts.CancelAfter(readTimeout);
sl@0
  2181
sl@0
  2182
									// Specify the function to call on a timeout.
sl@0
  2183
sl@0
  2184
									cts.Token.Register(onReadTimeoutAction);
sl@0
  2185
sl@0
  2186
									// Stops waiting when data is available or on timeout:
sl@0
  2187
sl@0
  2188
									Int32 bytesRead = await _myHid.GetInputReportViaInterruptTransfer(_deviceData, inputReportBuffer, cts);
sl@0
  2189
sl@0
  2190
									// Arrive here only if the operation completed.
sl@0
  2191
sl@2
  2192
									// Dispose to stop the timeout timer.
sl@0
  2193
sl@0
  2194
									cts.Dispose();
sl@0
  2195
sl@0
  2196
									_transferInProgress = false;
sl@0
  2197
									cmdGetInputReportInterrupt.Enabled = true;
sl@0
  2198
sl@0
  2199
									if (bytesRead > 0)
sl@0
  2200
									{
sl@0
  2201
										success = true;
sl@0
  2202
										Debug.Print("bytes read (includes report ID) = " + Convert.ToString(bytesRead));
sl@0
  2203
									}
sl@0
  2204
								}
sl@0
  2205
							}
sl@0
  2206
						}
sl@0
  2207
						else
sl@0
  2208
						{
sl@0
  2209
							MyMarshalDataToForm(FormActions.AddItemToListBox, "No attempt to read an Input report was made.");
sl@0
  2210
							MyMarshalDataToForm(FormActions.AddItemToListBox, "The HID doesn't have an Input report.");
sl@0
  2211
						}
sl@0
  2212
					}
sl@0
  2213
					else
sl@0
  2214
					{
sl@0
  2215
						MyMarshalDataToForm(FormActions.AddItemToListBox, "Invalid handle.");
sl@0
  2216
						MyMarshalDataToForm(FormActions.AddItemToListBox,
sl@0
  2217
											"No attempt to write an Output report or read an Input report was made.");
sl@0
  2218
					}
sl@0
  2219
sl@0
  2220
					if (success)
sl@0
  2221
					{
sl@0
  2222
						DisplayReportData(inputReportBuffer, ReportTypes.Input, ReportReadOrWritten.Read);
sl@0
  2223
					}
sl@0
  2224
					else
sl@0
  2225
					{
sl@0
  2226
						CloseCommunications();
sl@0
  2227
						MyMarshalDataToForm(FormActions.AddItemToListBox, "The attempt to read an Input report has failed.");
sl@0
  2228
						ScrollToBottomOfListBox();
sl@0
  2229
					}
sl@0
  2230
				}
sl@0
  2231
			}
sl@0
  2232
			catch (Exception ex)
sl@0
  2233
			{
sl@0
  2234
				DisplayException(Name, ex);
sl@0
  2235
				throw;
sl@0
  2236
			}
sl@0
  2237
		}
sl@0
  2238
sl@0
  2239
		///  <summary>
sl@0
  2240
		///  Sends a Feature report.
sl@0
  2241
		///  Assumes report ID = 0.
sl@0
  2242
		///  </summary>
sl@0
  2243
sl@0
  2244
		private void RequestToSendFeatureReport()
sl@0
  2245
		{
sl@0
  2246
			String byteValue = null;
sl@0
  2247
sl@0
  2248
			try
sl@0
  2249
			{
sl@0
  2250
				_transferInProgress = true;
sl@0
  2251
sl@0
  2252
				//  If the device hasn't been detected, was removed, or timed out on a previous attempt
sl@0
  2253
				//  to access it, look for the device.
sl@0
  2254
sl@0
  2255
				if (!_deviceHandleObtained)
sl@0
  2256
				{
sl@0
  2257
					_deviceHandleObtained = FindTheHid();
sl@0
  2258
				}
sl@0
  2259
sl@0
  2260
				if (_deviceHandleObtained)
sl@0
  2261
				{
sl@0
  2262
					GetBytesToSend();
sl@0
  2263
sl@0
  2264
					if ((_myHid.Capabilities.FeatureReportByteLength > 0))
sl@0
  2265
					{
sl@0
  2266
						//  The HID has a Feature report.
sl@2
  2267
						//  Set the size of the Feature report buffer.
sl@0
  2268
sl@0
  2269
						var outFeatureReportBuffer = new Byte[_myHid.Capabilities.FeatureReportByteLength];
sl@0
  2270
sl@0
  2271
						//  Store the report ID in the buffer.
sl@0
  2272
sl@0
  2273
						outFeatureReportBuffer[0] = 0;
sl@0
  2274
sl@0
  2275
						//  Store the report data following the report ID.
sl@0
  2276
						//  Use the data in the combo boxes on the form.
sl@0
  2277
sl@0
  2278
						outFeatureReportBuffer[1] = Convert.ToByte(CboByte0.SelectedIndex);
sl@0
  2279
sl@0
  2280
						if (outFeatureReportBuffer.GetUpperBound(0) > 1)
sl@0
  2281
						{
sl@0
  2282
							outFeatureReportBuffer[2] = Convert.ToByte(CboByte1.SelectedIndex);
sl@0
  2283
						}
sl@0
  2284
sl@0
  2285
						//  Write a report to the device
sl@0
  2286
sl@0
  2287
						Boolean success = _myHid.SendFeatureReport(_hidHandle, outFeatureReportBuffer);
sl@0
  2288
sl@0
  2289
						if (success)
sl@0
  2290
						{
sl@0
  2291
							DisplayReportData(outFeatureReportBuffer, ReportTypes.Feature, ReportReadOrWritten.Written);
sl@0
  2292
						}
sl@0
  2293
						else
sl@0
  2294
						{
sl@0
  2295
							CloseCommunications();
sl@0
  2296
							AccessForm(FormActions.AddItemToListBox, "The attempt to send a Feature report failed.");
sl@0
  2297
							ScrollToBottomOfListBox();
sl@0
  2298
						}
sl@0
  2299
					}
sl@0
  2300
					else
sl@0
  2301
					{
sl@0
  2302
						AccessForm(FormActions.AddItemToListBox, "The HID doesn't have a Feature report.");
sl@0
  2303
						ScrollToBottomOfListBox();
sl@0
  2304
					}
sl@0
  2305
sl@0
  2306
				}
sl@0
  2307
				_transferInProgress = false;
sl@0
  2308
				cmdSendFeatureReport.Enabled = true;
sl@0
  2309
				ScrollToBottomOfListBox();
sl@0
  2310
sl@0
  2311
			}
sl@0
  2312
			catch (Exception ex)
sl@0
  2313
			{
sl@0
  2314
				DisplayException(Name, ex);
sl@0
  2315
				throw;
sl@0
  2316
			}
sl@0
  2317
		}
sl@0
  2318
sl@0
  2319
		///  <summary>
sl@0
  2320
		///  Sends an Output report.
sl@0
  2321
		///  Assumes report ID = 0.
sl@0
  2322
		///  </summary>
sl@0
  2323
sl@0
  2324
		private async void RequestToSendOutputReport()
sl@0
  2325
		{
sl@0
  2326
			const Int32 writeTimeout = 5000;
sl@0
  2327
			String byteValue = null;
sl@0
  2328
sl@0
  2329
			try
sl@0
  2330
			{
sl@0
  2331
				//  If the device hasn't been detected, was removed, or timed out on a previous attempt
sl@0
  2332
				//  to access it, look for the device.
sl@0
  2333
sl@0
  2334
				if (!_deviceHandleObtained)
sl@0
  2335
				{
sl@0
  2336
					_deviceHandleObtained = FindTheHid();
sl@0
  2337
				}
sl@0
  2338
sl@0
  2339
				if (_deviceHandleObtained)
sl@0
  2340
				{
sl@0
  2341
					GetBytesToSend();
sl@0
  2342
				}
sl@0
  2343
				//  Don't attempt to exchange reports if valid handles aren't available
sl@0
  2344
				//  (as for a mouse or keyboard.)
sl@0
  2345
sl@0
  2346
				if (!_hidHandle.IsInvalid)
sl@0
  2347
				{
sl@0
  2348
					//  Don't attempt to send an Output report if the HID has no Output report.
sl@0
  2349
sl@0
  2350
					if (_myHid.Capabilities.OutputReportByteLength > 0)
sl@0
  2351
					{
sl@2
  2352
						//  Set the size of the Output report buffer.
sl@0
  2353
sl@0
  2354
						var outputReportBuffer = new Byte[_myHid.Capabilities.OutputReportByteLength];
sl@0
  2355
sl@0
  2356
						//  Store the report ID in the first byte of the buffer:
sl@0
  2357
sl@0
  2358
						outputReportBuffer[0] = 0;
sl@0
  2359
sl@0
  2360
						//  Store the report data following the report ID.
sl@0
  2361
						//  Use the data in the combo boxes on the form.
sl@0
  2362
sl@0
  2363
						outputReportBuffer[1] = Convert.ToByte(CboByte0.SelectedIndex);
sl@0
  2364
sl@0
  2365
						if (outputReportBuffer.GetUpperBound(0) > 1)
sl@0
  2366
						{
sl@0
  2367
							outputReportBuffer[2] = Convert.ToByte(CboByte1.SelectedIndex);
sl@0
  2368
						}
sl@0
  2369
sl@0
  2370
						//  Write a report.
sl@0
  2371
sl@0
  2372
						Boolean success;
sl@0
  2373
sl@0
  2374
						if (_transferType.Equals(TransferTypes.Control))
sl@0
  2375
						{
sl@0
  2376
							{
sl@0
  2377
								_transferInProgress = true;
sl@0
  2378
sl@0
  2379
								//  Use a control transfer to send the report,
sl@0
  2380
								//  even if the HID has an interrupt OUT endpoint.
sl@0
  2381
sl@0
  2382
								success = _myHid.SendOutputReportViaControlTransfer(_hidHandle, outputReportBuffer);
sl@0
  2383
sl@0
  2384
								_transferInProgress = false;
sl@0
  2385
								cmdSendOutputReportControl.Enabled = true;
sl@0
  2386
							}
sl@0
  2387
						}
sl@0
  2388
						else
sl@0
  2389
						{
sl@0
  2390
							Debug.Print("interrupt");
sl@0
  2391
							_transferInProgress = true;
sl@0
  2392
sl@0
  2393
							// The CancellationTokenSource specifies the timeout value and the action to take on a timeout.
sl@0
  2394
sl@0
  2395
							var cts = new CancellationTokenSource();
sl@0
  2396
sl@0
  2397
							// Create a delegate to execute on a timeout.
sl@0
  2398
sl@0
  2399
							Action onWriteTimeoutAction = OnWriteTimeout;
sl@0
  2400
sl@0
  2401
							// Cancel the read if it hasn't completed after a timeout.
sl@0
  2402
sl@0
  2403
							cts.CancelAfter(writeTimeout);
sl@0
  2404
sl@0
  2405
							// Specify the function to call on a timeout.
sl@0
  2406
sl@0
  2407
							cts.Token.Register(onWriteTimeoutAction);
sl@0
  2408
sl@0
  2409
							// Send an Output report and wait for completion or timeout.
sl@0
  2410
sl@0
  2411
							success = await _myHid.SendOutputReportViaInterruptTransfer(_deviceData, _hidHandle, outputReportBuffer, cts);
sl@0
  2412
sl@0
  2413
							// Get here only if the operation completes without a timeout.
sl@0
  2414
sl@0
  2415
							_transferInProgress = false;
sl@0
  2416
							cmdSendOutputReportInterrupt.Enabled = true;
sl@0
  2417
sl@0
  2418
							// Dispose to stop the timeout timer.
sl@0
  2419
sl@0
  2420
							cts.Dispose();
sl@0
  2421
						}
sl@0
  2422
						if (success)
sl@0
  2423
						{
sl@0
  2424
							DisplayReportData(outputReportBuffer, ReportTypes.Output, ReportReadOrWritten.Written);
sl@0
  2425
						}
sl@0
  2426
						else
sl@0
  2427
						{
sl@0
  2428
							CloseCommunications();
sl@0
  2429
							AccessForm(FormActions.AddItemToListBox, "The attempt to write an Output report failed.");
sl@0
  2430
							ScrollToBottomOfListBox();
sl@0
  2431
						}
sl@0
  2432
					}
sl@0
  2433
				}
sl@0
  2434
				else
sl@0
  2435
				{
sl@0
  2436
					AccessForm(FormActions.AddItemToListBox, "The HID doesn't have an Output report.");
sl@0
  2437
				}
sl@0
  2438
			}
sl@0
  2439
			catch (Exception ex)
sl@0
  2440
			{
sl@0
  2441
				DisplayException(Name, ex);
sl@0
  2442
				throw;
sl@0
  2443
			}
sl@0
  2444
		}
sl@0
  2445
sl@0
  2446
		///  <summary>
sl@0
  2447
		///  Scroll to the bottom of the list box and trim as needed.
sl@0
  2448
		///  </summary>
sl@0
  2449
sl@0
  2450
		private void ScrollToBottomOfListBox()
sl@0
  2451
		{
sl@0
  2452
			try
sl@0
  2453
			{
sl@0
  2454
				LstResults.SelectedIndex = LstResults.Items.Count - 1;
sl@0
  2455
sl@0
  2456
				//  If the list box is getting too large, trim its contents by removing the earliest data.
sl@0
  2457
sl@0
  2458
				if (LstResults.Items.Count > 1000)
sl@0
  2459
				{
sl@0
  2460
					Int32 count;
sl@0
  2461
					for (count = 1; count <= 500; count++)
sl@0
  2462
					{
sl@0
  2463
						LstResults.Items.RemoveAt(4);
sl@0
  2464
					}
sl@0
  2465
				}
sl@0
  2466
			}
sl@0
  2467
			catch (Exception ex)
sl@0
  2468
			{
sl@0
  2469
				DisplayException(Name, ex);
sl@0
  2470
				throw;
sl@0
  2471
			}
sl@0
  2472
		}
sl@0
  2473
sl@0
  2474
		/// <summary>
sl@0
  2475
		/// Request to send or get a Feature report.
sl@0
  2476
		/// </summary>
sl@0
  2477
sl@0
  2478
		private void SendOrGetFeatureReport()
sl@0
  2479
		{
sl@0
  2480
			try
sl@0
  2481
			{
sl@0
  2482
				//  If the device hasn't been detected, was removed, or timed out on a previous attempt
sl@0
  2483
				//  to access it, look for the device.
sl@0
  2484
sl@0
  2485
				if (!_deviceHandleObtained)
sl@0
  2486
				{
sl@0
  2487
					_deviceHandleObtained = FindTheHid();
sl@0
  2488
				}
sl@0
  2489
sl@0
  2490
				if (_deviceHandleObtained)
sl@0
  2491
				{
sl@0
  2492
					switch (_sendOrGet)
sl@0
  2493
					{
sl@0
  2494
						case SendOrGet.Send:
sl@0
  2495
							RequestToSendFeatureReport();
sl@0
  2496
							_sendOrGet = SendOrGet.Get;
sl@0
  2497
							break;
sl@0
  2498
						case SendOrGet.Get:
sl@0
  2499
							RequestToGetFeatureReport();
sl@0
  2500
							_sendOrGet = SendOrGet.Send;
sl@0
  2501
							break;
sl@0
  2502
					}
sl@0
  2503
				}
sl@0
  2504
			}
sl@0
  2505
			catch (Exception ex)
sl@0
  2506
			{
sl@0
  2507
				DisplayException(Name, ex);
sl@0
  2508
				throw;
sl@0
  2509
			}
sl@0
  2510
		}
sl@0
  2511
sl@0
  2512
		/// <summary>
sl@0
  2513
		/// Request to send an Output report or get an Input report.
sl@0
  2514
		/// </summary>
sl@0
  2515
sl@0
  2516
		private void SendOutputReportOrGetInputReport()
sl@0
  2517
		{
sl@0
  2518
			try
sl@0
  2519
			{
sl@0
  2520
				//  If the device hasn't been detected, was removed, or timed out on a previous attempt
sl@0
  2521
				//  to access it, look for the device.
sl@0
  2522
sl@0
  2523
				if (!_deviceHandleObtained)
sl@0
  2524
				{
sl@0
  2525
					_deviceHandleObtained = FindTheHid();
sl@0
  2526
				}
sl@0
  2527
sl@0
  2528
				if (_deviceHandleObtained)
sl@0
  2529
				{
sl@0
  2530
					if (_sendOrGet == SendOrGet.Send)
sl@0
  2531
					{
sl@0
  2532
						RequestToSendOutputReport();
sl@0
  2533
						_sendOrGet = SendOrGet.Get;
sl@0
  2534
					}
sl@0
  2535
					else
sl@0
  2536
					{
sl@0
  2537
						RequestToGetInputReport();
sl@0
  2538
						_sendOrGet = SendOrGet.Send;
sl@0
  2539
					}
sl@0
  2540
				}
sl@0
  2541
			}
sl@0
  2542
			catch (Exception ex)
sl@0
  2543
			{
sl@0
  2544
				DisplayException(Name, ex);
sl@0
  2545
				throw;
sl@0
  2546
			}
sl@0
  2547
		}
sl@0
  2548
sl@0
  2549
		///  <summary>
sl@2
  2550
		///  Set the number of Input buffers (the number of Input reports
sl@0
  2551
		///  the host will store) from the value in the text box.
sl@0
  2552
		///  </summary>
sl@0
  2553
sl@0
  2554
		private void SetInputReportBufferSize()
sl@0
  2555
		{
sl@0
  2556
			try
sl@0
  2557
			{
sl@0
  2558
				if (!_transferInProgress)
sl@0
  2559
				{
sl@0
  2560
					//  Get the number of buffers from the text box.
sl@0
  2561
sl@0
  2562
					Int32 numberOfInputBuffers = Convert.ToInt32(txtInputReportBufferSize.Text);
sl@0
  2563
sl@0
  2564
					//  Set the number of buffers.
sl@0
  2565
sl@0
  2566
					_myHid.SetNumberOfInputBuffers(_hidHandle, numberOfInputBuffers);
sl@0
  2567
sl@0
  2568
					//  Verify and display the result.
sl@0
  2569
sl@0
  2570
					GetInputReportBufferSize();
sl@0
  2571
				}
sl@0
  2572
				else
sl@0
  2573
				{
sl@0
  2574
					DisplayTransferInProgressMessage();
sl@0
  2575
				}
sl@0
  2576
			}
sl@0
  2577
			catch (Exception ex)
sl@0
  2578
			{
sl@0
  2579
				DisplayException(Name, ex);
sl@0
  2580
				throw;
sl@0
  2581
			}
sl@0
  2582
		}
sl@0
  2583
sl@0
  2584
		///  <summary>
sl@0
  2585
		///  Perform actions that must execute when the program ends.
sl@0
  2586
		///  </summary>
sl@0
  2587
sl@0
  2588
		private void Shutdown()
sl@0
  2589
		{
sl@0
  2590
			try
sl@0
  2591
			{
sl@0
  2592
				CloseCommunications();
sl@0
  2593
				DeviceNotificationsStop();
sl@0
  2594
			}
sl@0
  2595
			catch (Exception ex)
sl@0
  2596
			{
sl@0
  2597
				DisplayException(Name, ex);
sl@0
  2598
				throw;
sl@0
  2599
			}
sl@0
  2600
		}
sl@0
  2601
sl@0
  2602
		///  <summary>
sl@0
  2603
		///  Perform actions that must execute when the program starts.
sl@0
  2604
		///  </summary>
sl@0
  2605
sl@0
  2606
		private void Startup()
sl@0
  2607
		{
sl@0
  2608
			const Int32 periodicTransferInterval = 1000;
sl@0
  2609
			try
sl@0
  2610
			{
sl@0
  2611
				_myHid = new Hid();
sl@0
  2612
				InitializeDisplay();
sl@0
  2613
sl@0
  2614
				_periodicTransfers = new System.Timers.Timer(periodicTransferInterval);
sl@0
  2615
				_periodicTransfers.Elapsed += DoPeriodicTransfers;
sl@0
  2616
				_periodicTransfers.Stop();
sl@0
  2617
				_periodicTransfers.SynchronizingObject = this;
sl@0
  2618
sl@0
  2619
				//  Default USB Vendor ID and Product ID:
sl@0
  2620
sl@0
  2621
				txtVendorID.Text = "0925";
sl@0
  2622
				txtProductID.Text = "7001";
sl@0
  2623
sl@0
  2624
				GetVendorAndProductIDsFromTextBoxes(ref _myVendorId, ref _myProductId);
sl@0
  2625
sl@0
  2626
				DeviceNotificationsStart();
sl@0
  2627
				FindDeviceUsingWmi();
sl@0
  2628
				FindTheHid();
sl@0
  2629
			}
sl@0
  2630
			catch (Exception ex)
sl@0
  2631
			{
sl@0
  2632
				DisplayException(Name, ex);
sl@0
  2633
				throw;
sl@0
  2634
			}
sl@0
  2635
		}
sl@0
  2636
sl@0
  2637
		///  <summary>
sl@0
  2638
		///  The Product ID has changed in the text box. Call a routine to handle it.
sl@0
  2639
		///  </summary>
sl@0
  2640
sl@0
  2641
		private void txtProductID_TextChanged(Object sender, EventArgs e)
sl@0
  2642
		{
sl@0
  2643
			try
sl@0
  2644
			{
sl@0
  2645
				DeviceHasChanged();
sl@0
  2646
			}
sl@0
  2647
			catch (Exception ex)
sl@0
  2648
			{
sl@0
  2649
				DisplayException(Name, ex);
sl@0
  2650
				throw;
sl@0
  2651
			}
sl@0
  2652
		}
sl@0
  2653
sl@0
  2654
		///  <summary>
sl@0
  2655
		///  The Vendor ID has changed in the text box. Call a routine to handle it.
sl@0
  2656
		///  </summary>
sl@0
  2657
sl@0
  2658
		private void txtVendorID_TextChanged(Object sender, EventArgs e)
sl@0
  2659
		{
sl@0
  2660
			try
sl@0
  2661
			{
sl@0
  2662
				DeviceHasChanged();
sl@0
  2663
			}
sl@0
  2664
			catch (Exception ex)
sl@0
  2665
			{
sl@0
  2666
				DisplayException(Name, ex);
sl@0
  2667
				throw;
sl@0
  2668
			}
sl@0
  2669
		}
sl@0
  2670
sl@0
  2671
		///  <summary>
sl@0
  2672
		///  Provides a central mechanism for exception handling.
sl@0
  2673
		///  Displays a message box that describes the exception.
sl@0
  2674
		///  </summary>
sl@2
  2675
		///
sl@0
  2676
		///  <param name="moduleName"> the module where the exception occurred. </param>
sl@0
  2677
		///  <param name="e"> the exception </param>
sl@0
  2678
sl@0
  2679
		internal static void DisplayException(String moduleName, Exception e)
sl@0
  2680
		{
sl@0
  2681
			//  Create an error message.
sl@0
  2682
sl@0
  2683
			String message = "Exception: " + e.Message + Environment.NewLine + "Module: " + moduleName + Environment.NewLine + "Method: " + e.TargetSite.Name;
sl@0
  2684
sl@0
  2685
			const String caption = "Unexpected Exception";
sl@0
  2686
sl@0
  2687
			MessageBox.Show(message, caption, MessageBoxButtons.OK);
sl@0
  2688
			Debug.Write(message);
sl@0
  2689
sl@2
  2690
			// Get the last error and display it.
sl@0
  2691
sl@0
  2692
			Int32 error = Marshal.GetLastWin32Error();
sl@0
  2693
sl@0
  2694
			Debug.WriteLine("The last Win32 Error was: " + error);
sl@0
  2695
		}
sl@0
  2696
sl@0
  2697
		[STAThread]
sl@0
  2698
		internal static void Main() { Application.Run(new FrmMain()); }
sl@0
  2699
		private static FrmMain _transDefaultFormFrmMain;
sl@0
  2700
		internal static FrmMain TransDefaultFormFrmMain
sl@0
  2701
		{
sl@0
  2702
			get
sl@0
  2703
			{
sl@0
  2704
				if (_transDefaultFormFrmMain == null)
sl@0
  2705
				{
sl@0
  2706
					_transDefaultFormFrmMain = new FrmMain();
sl@0
  2707
				}
sl@0
  2708
				return _transDefaultFormFrmMain;
sl@0
  2709
			}
sl@0
  2710
		}
sl@0
  2711
	}
sl@0
  2712
}