C#与USBHID接口的通讯相对于与串口间的通讯较为复杂,其中需要多次调用到Windows的一些API。其原理编者尚未全部理清,以下提供简单的USBHID通讯流程。(参考网友资料)
一、获取所有连接HID的设备信息。
1.通过一个空的GUID来获取HID的全局GUID。
Guid HIDGuid = Guid.Empty;
///
/// The HidD_GetHidGuid routine returns the device interface GUID for HIDClass devices.
///
/// a caller-allocated GUID buffer that the routine uses to return the device interface GUID for HIDClass devices.
[DllImport("hid.dll")]
private static extern void HidD_GetHidGuid(ref Guid HidGuid);
2.通过获取到的HID全局GUID来获取包含所有HID接口信息集合的句柄。
IntPtr HIDInfoSet= SetupDiGetClassDevs(ref HIDGuid,0,IntPtr.Zero,DIGCF.DIGCF_PRESENT|DIGCF.DIGCF_DEVICEINTERFACE);
///
/// The SetupDiGetClassDevs function returns a handle to a device information set that contains requested device information elements for a local machine.
///
/// GUID for a device setup class or a device interface class.
/// A pointer to a NULL-terminated string that supplies the name of a PnP enumerator or a PnP device instance identifier.
/// A handle of the top-level window to be used for a user interface
/// A variable that specifies control options that filter the device information elements that are added to the device information set.
///
/// a handle to a device information set
[DllImport("setupapi.dll", SetLastError = true)]
private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, uint Enumerator, IntPtr HwndParent, USBHIDEnum.DIGCF Flags);
相关枚举:
public enum DIGCF
{
DIGCF_DEFAULT = 0x00000001,
DIGCF_PRESENT = 0x00000002,
DIGCF_ALLCLASSES = 0x00000004,
DIGCF_PROFILE = 0x00000008,
DIGCF_DEVICEINTERFACE = 0x00000010
}
3.获取接口信息。
///
/// The SetupDiEnumDeviceInterfaces function enumerates the device interfaces that are contained in a device information set.
///
/// A pointer to a device information set that contains the device interfaces for which to return information
/// A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet
/// a GUID that specifies the device interface class for the requested interface
/// A zero-based index into the list of interfaces in the device information set
/// a caller-allocated buffer that contains a completed SP_DEVICE_INTERFACE_DATA structure that identifies an interface that meets the search parameters
///
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr deviceInfoSet, IntPtr deviceInfoData, ref Guid interfaceClassGuid, UInt32 memberIndex, ref DEVICE_INTERFACE_DATA deviceInterfaceData);
接口信息定义为:
public struct DEVICE_INTERFACE_DATA
{
public int cbSize;
public Guid interfaceClassGuid;
public int flags;
public int reserved;
}
4.获取接口详细信息,在第一次主要是读取缓存信息
int requiredSize =0;
///
/// The SetupDiGetDeviceInterfaceDetail function returns details about a device interface.
///
/// A pointer to the device information set that contains the interface for which to retrieve details
/// A pointer to an SP_DEVICE_INTERFACE_DATA structure that specifies the interface in DeviceInfoSet for which to retrieve details
/// A pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA structure to receive information about the specified interface
/// The size of the DeviceInterfaceDetailData buffer
/// A pointer to a variable that receives the required size of the DeviceInterfaceDetailData buffer
/// A pointer buffer to receive information about the device that supports the requested interface
///
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr deviceInfoSet, ref DEVICE_INTERFACE_DATA deviceInterfaceData, IntPtr deviceInterfaceDetailData, int deviceInterfaceDetailDataSize, ref int requiredSize, DEVINFO_DATA deviceInfoData);
接口信息定义:
[StructLayout(LayoutKind.Sequential)]
public class DEVINFO_DATA
{
public int cbSize = Marshal.SizeOf(typeof(DEVINFO_DATA));
public Guid classGuid = Guid.Empty;
public int devInst = 0;
public int reserved = 0;
}
5.第二次获取详细信息,与第一相同。
若Windows API SetupDiGetDeviceInterfaceDetail返回数值为true则添加设备信息
ListdeviceList=new List();
deviceList.Add(Marshal.PtrToStringAuto((IntPtr)((int)pDetail + 4)));
6.删除设备信息并释放内存。
///
/// The SetupDiDestroyDeviceInfoList function deletes a device information set and frees all associated memory.
///
/// A handle to the device information set to delete.
/// returns TRUE if it is successful. Otherwise, it returns FALSE
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr HIDInfoSet);
到此便获取到所有的设备。
二、通过获取到的设备信息打开指定的HID设备。
1.创建,打开设备信息。
///
/// This function creates, opens, or truncates a file, COM port, device, service, or console.
///
/// a null-terminated string that specifies the name of the object
/// Type of access to the object
/// Share mode for object
/// Ignored; set to NULL
/// Action to take on files that exist, and which action to take when files do not exist
/// File attributes and flags for the file
/// Ignored
/// An open handle to the specified file indicates success
[DllImport("kernel32.dll", SetLastError = true)]
//private static extern IntPtr CreateFile(string fileName, uint desiredAccess, uint shareMode, uint securityAttributes, uint creationDisposition, uint flagsAndAttributes, uint templateFile);
static extern IntPtr CreateFile(
string FileName, // 文件名
uint DesiredAccess, // 访问模式
uint ShareMode, // 共享模式
uint SecurityAttributes, // 安全属性
uint CreationDisposition, // 如何创建
uint FlagsAndAttributes, // 文件属性
int hTemplateFile // 模板文件的句柄
);
其中文件名为相对应的设备名deviceList[index]
2.获取设备属性
///
/// The HidD_GetAttributes routine returns the attributes of a specified top-level collection.
///
/// Specifies an open handle to a top-level collection
/// a caller-allocated HIDD_ATTRIBUTES structure that returns the attributes of the collection specified by HidDeviceObject
///
[DllImport("hid.dll")]
private static extern Boolean HidD_GetAttributes(IntPtr hidDevice, out HID_ATTRIBUTES attributes);
相关HID属性:
public struct HID_ATTRIBUTES
{
public int Size;
public ushort VendorID;
public ushort ProductID;
public ushort VersionNumber;
}
3.Get PreparsedData
///
/// The HidD_GetPreparsedData routine returns a top-level collection's preparsed data.
///
/// Specifies an open handle to a top-level collection.
/// Pointer to the address of a routine-allocated buffer that contains a collection's preparsed data in a _HIDP_PREPARSED_DATA structure.
/// HidD_GetPreparsedData returns TRUE if it succeeds; otherwise, it returns FALSE.
[DllImport("hid.dll")]
private static extern Boolean HidD_GetPreparsedData(IntPtr hidDeviceObject, out IntPtr PreparsedData);
4. GetCaps
[DllImport("hid.dll")]
private static extern uint HidP_GetCaps(IntPtr PreparsedData, out HIDP_CAPS Capabilities);
5. FreePreparsedData
[DllImport("hid.dll")]
private static extern Boolean HidD_FreePreparsedData(IntPtr PreparsedData);
6.获取长度:
outputReportLength = caps.OutputReportByteLength;
inputReportLength = caps.InputReportByteLength;
7.最终得到相应的设备
hidDevice = new FileStream(new SafeFileHandle(device, false), FileAccess.ReadWrite, inputReportLength, true);
三、设备读取,写入
通过最终获取到的设备可对设备进行读取和写入。
BeginRead,Read,Write,BeginWrite等。
以上便能实现对想要的USBHID设备进行简单的操作。
简单串口例子: http://blog.sina.com.cn/s/blog_6267db160102v53m.html