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