C#与USB HID间的通信

原文:C#与USB HID间的通信

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

示例代码下载地址:http://download.csdn.net/detail/zhezizhang/8155795

时间: 2024-09-14 07:39:50

C#与USB HID间的通信的相关文章

如何通过交换机的VTP技术实现不同Vlan和不同网络间的通信

三层交换技术就是二层交换技术加三层路由转发技术,传统的交换技术在数据链路层进行操作,三层交换技术是在网络层实现数据包的高速转发.应用第三层交换技术即可实现网络路由的功能,又可以根据不同的网络状况做到最优的网络性能.三层交换机最重要的目的是加大大型局域网内部的数据交换,并不能取代路由器的工作,处于同一个局域网中各个子网的互联以及局域网中Vlan间的路由,用三层交换机来代替路由器,而只有局域网与公网互联网之间要实现跨越地域的网络访问时,才通过专业路由器. 了解了三层交换技术,我们下面通过交换机的VT

彻底明白Java的多线程-线程间的通信

线程间的通信 1. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种: 1) 产生(New):线程对象已经产生,但尚未被启动,所以无法执行.如通过new产生了一个线程对象后没对它调用start()函数之前. 2) 可执行(Runnable):每个支持多线程的系统都有一个排程器,排程器会从线程池中选择一个线程并启动它.当一个线程处于可执行状态时,表示它可能正处于线程池中等待排排程器启动它:也可能它已正在执行.如执行了一个线程对象的start()方法后,线程就处于可执行状态,但

集群-如何在ssh服务器间进行通信?

问题描述 如何在ssh服务器间进行通信? 我有一个问题,就是服务器端采用的是ssh架构,做成服务器集群,不同功能模块部署在不同服务器上,然后一个模块需要 调用部署在另外一台服务器上的模块,那么他们之间该如何通信呢? 解决方案 Fragment间进行通信 解决方案二: 用HTTP协议传说到Struts2,数据保存为json,直接提取解析就可以了 解决方案三: 不同应用间通讯的话,可以用socket来处理的.

信息交互-不同设备的编程语言不同怎么实现相互间的通信

问题描述 不同设备的编程语言不同怎么实现相互间的通信 我是个小白,就想问问,不同设备的编程语言不同怎么实现设备间的相互通信,比如我的单片机用keil编程写入c,中间一台设备用phython编程,另外一台是电脑控制,那请问怎么实现单片机,设备,电脑之间信息的交流与通信?跪求大神回答!!!在线等!!! 解决方案 标准的,可以都用socket来通信.tcp,udp等.只有双方沟通好协议格式 解决方案二: 单片机一般用串口和计算机通讯.双方约定好数据的格式就可以了.

linux虚拟机与windows间socket通信问题

问题描述 linux虚拟机与windows间socket通信问题 虚拟机linux服务端 windows客户端 虚拟机桥接模式,能互相ping到,但运行连接不上 linux Server #include #include #include #include #include #include #include #include #define BACKLOG 5 int main(int arge,char *argv[]) { int sockfd,new_fd; struct sockad

线程及 进程间的通信问题! .

一个很好的编程随想的博客http://program-think.blogspot.com/2009/03/producer-consumer-pattern-0-overview.html 架构设计:生产者/消费者模式[0]:概述  1.如何确定数据单元2.队列缓冲区3.环形缓冲区4.双缓冲区 生产 消费 2010-06-01 10:13   #include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp>

vb编程-三菱plc与上位vb编的界面间以太网通信

问题描述 三菱plc与上位vb编的界面间以太网通信 用vb的winsock编了个服务器,三菱plc做客户端,但一直连接不上,vb还需要装什么驱动软件吗,三菱plc用的是Q系列的,求指点 解决方案 求大神指点呀,江湖救急呀

udp-zeromq进程间的通信怎么使用?

问题描述 zeromq进程间的通信怎么使用? 我今天看了下zeromq,也用zeromq写了几个简单的例子,然后看了下它的介绍,发送支持好多通信协议,TCP.UDP.IPC 网上讲的例子都是讲TCP通信的,我想知道如果用来实现进程间的通信,这个要怎么用呢! 解决方案 client: C/C++ code #include #include #include #include int main () { void *context = zmq_init (1); // Socket to talk

ns2-求NS2下 ,运动100个节点和Sink间的通信仿真,其tcl脚本怎么写?谢谢。

问题描述 求NS2下 ,运动100个节点和Sink间的通信仿真,其tcl脚本怎么写?谢谢. NS2下 ,使用cbrgen生成了数据流,使用setdest设置了节点随机运动的场景, 但如何才能设置一个固定节点作为Sink,让其他节点的数据都传输给Sink呢? 其tcl脚本怎么写?谢谢. 解决方案 http://wenku.baidu.com/link?url=3GdBNjKmt65GsgN5riBqMNamd150QJfCmwn1VA4WX1_fieBsQd0pJr3qJ3AbLCweMcvNbp