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-08-01 19:24:44

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

Windows与自定义USB HID设备通信说明.

1 .   所使用的典型 Windows API CreateFile ReadFile WriteFile 以下函数是 DDK 的内容: HidD_SetFeature HidD_GetFeature HidD_SetOutputReport HidD_GetInputReport 其中, CreateFile 用于打开设备: ReadFile . HidD_GetFeature . HidD_GetInputReport 用于设备到主机方向的数据通信: WriteFile . HidD_Se

线程间的通信、同步方式与进程间通信方式

1.线程间的通信方式 1)使用全局变量(由于多个线程可能更改全局变量,因此全局变量最好声明为volatile) 2) 使用消息实现通信 3)使用事件CEvent类实现线程间的通信 2.同步/异步(C端) 同步:在C端发出一个功能调用时,没有得到结果之前就不返回 异步: 一个请求通过事件触发后,得到服务器处理后才处理完毕 3. 阻塞/非阻塞(S端) 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行).函数只有在得到

Android 使用AIDL实现进程间的通信

在Android中,如果我们需要在不同进程间实现通信,就需要用到AIDL技术去完成. AIDL(android Interface Definition Language)是一种接口定义语言,编译器通过*.aidl文件的描述信息生成符合通信协议的Java代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作.关于AIDL的编写规则我在这里就不多介绍了,读者可以到网上查找一下相关资料. 接下来,我就演示一个操作AIDL的最基本的流程. 首先,我

线程(二)__线程间的通信

线程间的通信:多个线程在处理同一资源,但是任务却不同.一.等待唤醒机制涉及的方法:1.wait();让线程处于冻结状态,被wait的线程会被存储到线程池中2.notify();唤醒线程池中的一个任意线程3.notifyAll();唤醒线程池中的所有线程这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个锁上的线程wait()对A锁上面的线程进行操作后只能用A锁的notify来唤醒.被wait之后的线程可认为放在线程池中. 为什么操作线程的方法wait no

进程间的通信如何实现

进程间的通信如何实现 版权声明:本文为博主原创文章,未经博主允许不得转载.

linux 进程间的通信

现在linux使用的进程间通信方式:(1)管道(pipe)和有名管道(FIFO)(2)信号(signal)(3)消息队列(4)共享内存(5)信号量(6)套接字(socket) 为何进行进程间的通信:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到.C.通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程).D.资源共享

Linux进程间的通信

一.管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: A. 管道是半双工的,数据只能向一个方向流动: B. 需要双工通信时,需要建立起两个管道: C. 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): D. 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 匿名管道的创建:该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义;因此,一

【转】使用AIDL实现进程间的通信之复杂类型传递

使用AIDL实现进程间的通信之复杂类型传递 首先要了解一下AIDL对Java类型的支持. 1.AIDL支持Java原始数据类型. 2.AIDL支持String和CharSequence. 3.AIDL支持传递其他AIDL接口,但你引用的每个AIDL接口都需要一个import语句,即使位于同一个包中. 4.AIDL支持传递实现了android.os.Parcelable接口的复杂类型,同样在引用这些类型时也需要import语句.(Parcelable接口告诉Android运行时在封送(marsha

Linux进程间的通信方法

linux进程间的通信方法总结如下 通过fork函数把打开文件的描述符传递给子进程 通过wait得到子进程的终结信息 通过加锁的方式,实现几个进行共享读写某个文件 进行间通过信号通信,SIGUSR1和SIGUSR2实现用户定义功能 利用pipe进行通信 FIFO文件进行通信 mmap,几个进程映射到同一内存区 SYS IPC 消息队列,信号量(很少用) UNIX Domain Socket,常用