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