using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Collections.Generic;
using System.Windows.Forms;
namespace MyUsbHid
{
public class UsbHid
{
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const int FILE_SHARE_READ = 1;
public const int FILE_SHARE_WRITE = 2;
public const int OPEN_EXISTING = 3;
public const int OPEN_ALWAYS = 4;
public const int FILE_ATTRIBUTE_NORMAL = 0x80;
public const int FILE_FLAG_OVERLAPPED = 0x40000000;
public const int DIGCF_DEFAULT = 0x1;
public const int DIGCF_PRESENT = 0x2;
public const int DIGCF_ALLCLASSES = 0x4;
public const int DIGCF_PROFILE = 0x8;
public const int DIGCF_DEVICEINTERFACE = 0x10;
public struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid classGuid;
public int DevInst;
public int reserved;
}
public struct SP_DEVICE_INTERFACE_DATA
{
public int cbSize;
public Guid InterfaceClassGuid;
public int flags;
public int reserved;
}
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public int cbSize;
public string devicePath;
}
// 获得GUID
[DllImport("hid.dll", SetLastError = true)]
public static extern void HidD_GetHidGuid(ref Guid HidGuid);
// 请求指向设备信息集的指针
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SetupDiGetClassDevs(
ref Guid ClassGuid,
IntPtr enumerator,
IntPtr HwndParent,
int flags);
// 标识设备接口
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetupDiEnumDeviceInterfaces(
IntPtr DeviceInfoSet,
IntPtr DeviceInfoData,
ref Guid InterfaceClassGuid,
int MemberIndex,
ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
// 请求带有设备类路径名的结构体
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetupDiGetDeviceInterfaceDetail(
IntPtr DeviceInfoSet,
ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
IntPtr DeviceInterfaceDetailData,
int DeviceInterfaceDetailDataSize,
ref int RequiredSize,
IntPtr DeviceInfoData);
// 释放DeviceInfoSet资源
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
// 请求通讯句柄
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern SafeFileHandle CreateFile(
string lpFileName, // 文件名
uint dwDesiredAccess, // 访问模式
int dwShareMode, // 共享模式
int lpSecurityAttributes, // 安全属性
int dwCreationDisposition, // 如何创建
int dwFlagsAndAttributes, // 如何创建
int hTemplateFile); // 模板文件的句柄
// 读取设备文件
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool ReadFile(
SafeFileHandle hFile,
byte[] lpBuffer,
uint nNumberOfBytesToRead,
ref uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
// 写设备文件
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool WriteFile(
SafeFileHandle hFile,
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
ref uint lpNumberOfBytesWrite,
IntPtr lpOverlapped);
// 发现所有已连接的HID设备
public static void FindAllHidDevices(ref List DeviceList)
{
Guid HidGuid = Guid.Empty;
HidD_GetHidGuid(ref HidGuid);
// 请求指向设备信息集的指针
IntPtr DeviceInfoSet;
DeviceInfoSet = SetupDiGetClassDevs(ref HidGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (DeviceInfoSet == IntPtr.Zero)
{
return;
}
int MemberIndex;
bool result = true;
for (MemberIndex = 0; ; MemberIndex++)
{
SP_DEVICE_INTERFACE_DATA MyDevInterfaceData = new SP_DEVICE_INTERFACE_DATA();
MyDevInterfaceData.cbSize = Marshal.SizeOf(MyDevInterfaceData);
result = SetupDiEnumDeviceInterfaces(DeviceInfoSet, IntPtr.Zero, ref HidGuid, MemberIndex, ref MyDevInterfaceData);
if (!result)
{
break;
}
int BufferSize = 0;
// 第一次调用返回BufferSize的大小
SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDevInterfaceData, IntPtr.Zero, 0, ref BufferSize, IntPtr.Zero);
IntPtr DetailDataBuffer = Marshal.AllocHGlobal(BufferSize);
Marshal.WriteInt32(DetailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
// 第二次调用返回含有设备路径名的结构体MyDevInterfaceData
result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDevInterfaceData, DetailDataBuffer, BufferSize, ref BufferSize, IntPtr.Zero);
if (result == true)
{
// 获取设备路径
IntPtr pDevicePathName = new IntPtr(DetailDataBuffer.ToInt32() + 4);
string DevicePathName = Marshal.PtrToStringAuto(pDevicePathName);
DeviceList.Add(DevicePathName);
}
Marshal.FreeHGlobal(DetailDataBuffer);
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
}
public class HidDevice
{
string DevicePathName;
SafeFileHandle HidHandle;
bool OpenStatus = false;
public HidDevice(string DevicePathName)
{
this.DevicePathName = DevicePathName;
}
// 使用阻塞调用打开文件句柄
public void open()
{
HidHandle = UsbHid.CreateFile(
DevicePathName,
UsbHid.GENERIC_READ | UsbHid.GENERIC_WRITE,
UsbHid.FILE_SHARE_READ | UsbHid.FILE_SHARE_WRITE,
0,
UsbHid.OPEN_EXISTING,
UsbHid.FILE_ATTRIBUTE_NORMAL,
0);
OpenStatus = true;
}
// 向HID设备写入数据
public bool WriteData(
byte[] buffer, // 指向一个缓冲区,放置准备写入的数据
ref uint length) // 指向长度单元,输入时为准备写入的长度,返回后为实际写入的长度
{
if (OpenStatus == false)
{
MessageBox.Show("请打开HID设备", "提示");
return false;
}
bool result;
uint NumOfWrite = 0;
result = UsbHid.WriteFile(HidHandle, buffer, length, ref NumOfWrite, IntPtr.Zero);
length = NumOfWrite;
if (!result)
{
return false;
}
return true;
}
// 从HID设备读取数据
public bool ReadData(
byte[] buffer, // 指向一个缓冲区,放置准备读出的数据
ref uint length) // 指向长度单元,输入时为准备读出的长度,返回后为实际读出的长度
{
if (OpenStatus == false)
{
MessageBox.Show("请打开HID设备", "提示");
return false;
}
bool result;
uint NumOfRead = 0;
result = UsbHid.ReadFile(HidHandle, buffer, length, ref NumOfRead, IntPtr.Zero);
length = NumOfRead;
if (!result)
{
return false;
}
return true;
}
public void close()
{
if (OpenStatus == false)
{
return;
}
OpenStatus = false;
HidHandle.Close();
}
}
}