📄 hid.cs
字号:
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace HID_Test_Application
{
// internal class Hid
class Hid {
// For communicating with HID-class devices.
// Used in error messages.
const string ModuleName = "Hid";
internal HidApiDeclarations.HIDP_CAPS Capabilities;
internal HidApiDeclarations.HIDD_ATTRIBUTES DeviceAttributes;
// For viewing results of API calls in debug.write statements:
static Debugging MyDebugging = new Debugging();
internal abstract class DeviceReport
{
// For reports that the device sends to the host.
internal int HIDHandle;
internal bool MyDeviceDetected;
internal int Result;
internal int ReadHandle;
// Each DeviceReport class defines a ProtectedRead method for reading a type of report.
// ProtectedRead and Read are declared as Subs rather than as Functions because
// asynchronous reads use a callback method that can access parameters passed by ByRef
// but not Function return values.
protected abstract void ProtectedRead (int readHandle, int hidHandle, ref bool myDeviceDetected, ref byte[] readBuffer, ref bool success);
internal void Read (int readHandle, int hidHandle, ref bool myDeviceDetected, ref byte[] readBuffer, ref bool success)
{
// Purpose : Calls the overridden ProtectedRead routine.
// Enables other classes to override ProtectedRead
// while limiting access as Friend.
// (Directly declaring Write as Friend MustOverride causes the
// compiler warning : "Other languages may permit Friend
// Overridable members to be overridden.")
// Accepts : readHandle - a handle for reading from the device.
// hidHandle - a handle for other device communications.
// myDeviceDetected - tells whether the device is currently
// attached and communicating.
// readBuffer - a byte array to hold the report ID and report data.
// success - read success
try {
// Request the report.
ProtectedRead(readHandle, hidHandle, ref myDeviceDetected, ref readBuffer, ref success);
} catch (Exception ex) {
HandleException(ModuleName + ":" + System.Reflection.MethodBase.GetCurrentMethod(), ex);
}
}
}
internal class InFeatureReport : DeviceReport
{
// For reading Feature reports.
protected override void ProtectedRead (int readHandle, int hidHandle, ref bool myDeviceDetected, ref byte[] inFeatureReportBuffer, ref bool success)
{
// Purpose : reads a Feature report from the device.
// Accepts : readHandle - the handle for reading from the device.
// hidHandle - the handle for other device communications.
// myDeviceDetected - tells whether the device is currently attached.
// readBuffer - contains the requested report.
// success - read success
try {
// ***
// API function: HidD_GetFeature
// Attempts to read a Feature report from the device.
// Requires:
// A handle to a HID
// A pointer to a buffer containing the report ID and report
// The size of the buffer.
// Returns: true on success, false on failure.
// ***
success = HidApiDeclarations.HidD_GetFeature(hidHandle, ref inFeatureReportBuffer[0], inFeatureReportBuffer.Length);
Debug.WriteLine(MyDebugging.ResultOfAPICall("ReadFile"));
Debug.WriteLine("");
} catch (Exception ex) {
HandleException(ModuleName + ":" + System.Reflection.MethodBase.GetCurrentMethod(), ex);
}
}
}
internal class InputReport : DeviceReport
{
// For reading Input reports.
bool ReadyForOverlappedTransfer; // initialize to false
internal void CancelTransfer (int readHandle, int hidHandle)
{
// Purpose : closes open handles to a device.
// Accepts : ReadHandle - the handle for reading from the device.
// HIDHandle - the handle for other device communications.
try {
// ***
// API function: CancelIo
// Purpose: Cancels a call to ReadFile
// Accepts: the device handle.
// Returns: True on success, False on failure.
// ***
Result = FileIOApiDeclarations.CancelIo(readHandle);
Debug.WriteLine("************ReadFile error*************");
Debug.WriteLine(MyDebugging.ResultOfAPICall("CancelIo"));
Debug.WriteLine("");
// The failure may have been because the device was removed,
// so close any open handles and
// set myDeviceDetected=False to cause the application to
// look for the device on the next attempt.
if (hidHandle != 0) {
FileIOApiDeclarations.CloseHandle(hidHandle);
Debug.WriteLine(MyDebugging.ResultOfAPICall("CloseHandle (HIDHandle)"));
Debug.WriteLine("");
}
if (hidHandle != 0) {
FileIOApiDeclarations.CloseHandle(readHandle);
Debug.WriteLine(MyDebugging.ResultOfAPICall("CloseHandle (ReadHandle)"));
}
} catch (Exception ex) {
HandleException(ModuleName + ":" + System.Reflection.MethodBase.GetCurrentMethod(), ex);
}
}
internal void PrepareForOverlappedTransfer (ref FileIOApiDeclarations.OVERLAPPED hidOverlapped, ref int eventObject)
{
// Purpose : Creates an event object for the overlapped structure used with
// : ReadFile.
// ; Called before the first call to ReadFile.
FileIOApiDeclarations.SECURITY_ATTRIBUTES Security = new HID_Test_Application.FileIOApiDeclarations.SECURITY_ATTRIBUTES();
try {
// Values for the SECURITY_ATTRIBUTES structure:
Security.lpSecurityDescriptor = 0;
Security.bInheritHandle = System.Convert.ToInt32(true);
Security.nLength = Marshal.SizeOf(Security);
// ***
// API function: CreateEvent
// Purpose: Creates an event object for the overlapped structure used with ReadFile.
// Accepts:
// A security attributes structure.
// Manual Reset = False (The system automatically resets the state to nonsignaled
// after a waiting thread has been released.)
// Initial state = True (signaled)
// An event object name (optional)
// Returns: a handle to the event object
// ***
eventObject = FileIOApiDeclarations.CreateEvent(ref Security, System.Convert.ToInt32(false), System.Convert.ToInt32(true), "");
Debug.WriteLine(MyDebugging.ResultOfAPICall("CreateEvent"));
Debug.WriteLine("");
// Set the members of the overlapped structure.
hidOverlapped.Offset = 0;
hidOverlapped.OffsetHigh = 0;
hidOverlapped.hEvent = eventObject;
ReadyForOverlappedTransfer = true;
} catch (Exception ex) {
HandleException(ModuleName + ":" + System.Reflection.MethodBase.GetCurrentMethod(), ex);
}
}
protected override void ProtectedRead (int readHandle, int hidHandle, ref bool myDeviceDetected, ref byte[] inputReportBuffer, ref bool success)
{
// Purpose : reads an Input report from the device using interrupt transfers.
// Accepts : readHandle - the handle for reading from the device.
// hidHandle - the handle for other device communications.
// myDeviceDetected - tells whether the device is currently attached.
// readBuffer - contains the requested report.
// success - read success
int EventObject = 0;
FileIOApiDeclarations.OVERLAPPED HIDOverlapped = new HID_Test_Application.FileIOApiDeclarations.OVERLAPPED();
int NumberOfBytesRead = 0;
long Result = 0;
try {
// If it's the first attempt to read, set up the overlapped structure for ReadFile.
if (!ReadyForOverlappedTransfer) {
PrepareForOverlappedTransfer(ref HIDOverlapped, ref EventObject);
}
// ***
// API function: ReadFile
// Purpose: Attempts to read an Input report from the device.
// Accepts:
// A device handle returned by CreateFile
// (for overlapped I/O, CreateFile must have been called with FILE_FLAG_OVERLAPPED),
// A pointer to a buffer for storing the report.
// The Input report length in bytes returned by HidP_GetCaps,
// A pointer to a variable that will hold the number of bytes read.
// An overlapped structure whose hEvent member is set to an event object.
// Returns: the report in ReadBuffer.
// The overlapped call returns immediately, even if the data hasn't been received yet.
// To read multiple reports with one ReadFile, increase the size of ReadBuffer
// and use NumberOfBytesRead to determine how many reports were returned.
// Use a larger buffer if the application can't keep up with reading each report
// individually.
// ***
Debug.Write("input report length = " + inputReportBuffer.Length);
Result = FileIOApiDeclarations.ReadFile(readHandle, ref inputReportBuffer[0], inputReportBuffer.Length, ref NumberOfBytesRead, ref HIDOverlapped);
Debug.WriteLine(MyDebugging.ResultOfAPICall("ReadFile"));
Debug.WriteLine("");
Debug.WriteLine("waiting for ReadFile");
// API function: WaitForSingleObject
// Purpose: waits for at least one report or a timeout.
// Used with overlapped ReadFile.
// Accepts:
// An event object created with CreateEvent
// A timeout value in milliseconds.
// Returns: A result code.
Result = FileIOApiDeclarations.WaitForSingleObject(EventObject, 3000);
Debug.WriteLine(MyDebugging.ResultOfAPICall("WaitForSingleObject"));
Debug.WriteLine("");
// Find out if ReadFile completed or timeout.
switch (Result) {
case FileIOApiDeclarations.WAIT_OBJECT_0:
// ReadFile has completed
Debug.WriteLine("");
success = true;
Debug.WriteLine("ReadFile completed successfully.");
break;
case FileIOApiDeclarations.WAIT_TIMEOUT:
// Cancel the operation on timeout
CancelTransfer(readHandle, hidHandle);
Debug.WriteLine("Readfile timeout");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -