C# 访问USB(HID)设备

原文:C# 访问USB(HID)设备

二话不说,直接给代码,如果您真想做这方面的东西,还是稍微研究下,没有现成的好类用,就需要自己了解其原理

//引用空间

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.Threading;

using System.Collections;

using System.IO;

//以下是调用windows的API的函数

//获得GUID

[DllImport("hid.dll")]

public static extern void HidD_GetHidGuid(ref Guid HidGuid);

Guid guidHID = Guid.Empty;

//过滤设备,获取需要的设备

[DllImport("setupapi.dll", SetLastError = true)]

public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, uint Enumerator, IntPtr HwndParent, DIGCF Flags);

IntPtr hDevInfo;

//获取设备,true获取到

[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]

public static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr hDevInfo, IntPtr devInfo, ref Guid interfaceClassGuid, UInt32 memberIndex, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData);

public struct SP_DEVICE_INTERFACE_DATA

{

public int cbSize ;

public Guid interfaceClassGuid;

public int flags;

public int reserved;

}

// 获取接口的详细信息 必须调用两次 第1次返回长度 第2次获取数据

[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]

private static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr deviceInfoSet, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, IntPtr deviceInterfaceDetailData,

int deviceInterfaceDetailDataSize, ref int requiredSize, SP_DEVINFO_DATA deviceInfoData);

[StructLayout(LayoutKind.Sequential)]

public class SP_DEVINFO_DATA

{

public int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));

public Guid classGuid = Guid.Empty; // temp

public int devInst = 0; // dumy

public int reserved = 0;

}

[StructLayout(LayoutKind.Sequential, Pack = 2)]

internal struct SP_DEVICE_INTERFACE_DETAIL_DATA

{

internal int cbSize;

internal short devicePath;

}

public enum DIGCF

{

DIGCF_DEFAULT = 0x1,

DIGCF_PRESENT = 0x2,

DIGCF_ALLCLASSES = 0x4,

DIGCF_PROFILE = 0x8,

DIGCF_DEVICEINTERFACE = 0x10

}

//获取设备文件

[DllImport("kernel32.dll", SetLastError = true)]

private static extern int CreateFile(

string lpFileName,                            // file name

uint dwDesiredAccess,                        // access mode

uint dwShareMode,                            // share mode

uint lpSecurityAttributes,                    // SD

uint dwCreationDisposition,                    // how to create

uint dwFlagsAndAttributes,                    // file attributes

uint hTemplateFile                            // handle to template file

);

//读取设备文件

[DllImport("Kernel32.dll",SetLastError = true)]

private static extern bool ReadFile

(

IntPtr hFile,

byte[] lpBuffer,

uint nNumberOfBytesToRead,

ref uint lpNumberOfBytesRead,

IntPtr lpOverlapped

);

//释放设备

[DllImport("hid.dll")]

static public extern bool HidD_FreePreparsedData(ref IntPtr PreparsedData);

//关闭访问设备句柄,结束进程的时候把这个加上保险点

[DllImport("kernel32.dll")]

static public extern int CloseHandle(int hObject);

接下来是访问设备的代码

//代码暂时没有整理,传入参数是设备序号,

//有些USB设备其实有很多HID设备,就是一个接口上有几个设备,这个时候需要

//用index++来逐个循环,直到获取设备返回false后,跳出去,把获取的设备

//路径全记录下来就好了,我这里知道具体设备号,所以没有循环,浪费我时间

//定于句柄序号和一些参数,具体可以去网上找这些API的参数说明,后文我看能不能把资料也写上去

int HidHandle = -1;

public const uint GENERIC_READ = 0x80000000;

public const uint GENERIC_WRITE = 0x40000000;

public const uint FILE_SHARE_READ= 0x00000001;

public const uint FILE_SHARE_WRITE = 0x00000002;

public const int OPEN_EXISTING = 3;

private void UsBMethod(int index)

{

HidD_GetHidGuid(ref guidHID);

hDevInfo = SetupDiGetClassDevs(ref guidHID, 0, IntPtr.Zero, DIGCF.DIGCF_PRESENT | DIGCF.DIGCF_DEVICEINTERFACE);

int bufferSize = 0;

ArrayList HIDUSBAddress = new ArrayList();

//while (true)

//{

//获取设备,true获取到

SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();

DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData);

//for (int i = 0; i < 3; i++)

//{

bool result = SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guidHID, (UInt32)index, ref DeviceInterfaceData);

//}

//第一次调用出错,但可以返回正确的Size

SP_DEVINFO_DATA strtInterfaceData = new SP_DEVINFO_DATA();

result = SetupDiGetDeviceInterfaceDetail(hDevInfo, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, strtInterfaceData);

//第二次调用传递返回值,调用即可成功

IntPtr detailDataBuffer = Marshal.AllocHGlobal(bufferSize);

SP_DEVICE_INTERFACE_DETAIL_DATA detailData = new SP_DEVICE_INTERFACE_DETAIL_DATA();

detailData.cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DETAIL_DATA));

Marshal.StructureToPtr(detailData, detailDataBuffer, false);

result = SetupDiGetDeviceInterfaceDetail(hDevInfo, ref DeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, strtInterfaceData);

if (result == false)

{

//break;

}

//获取设备路径访

IntPtr pdevicePathName = (IntPtr)((int)detailDataBuffer + 4);

string devicePathName = Marshal.PtrToStringAuto(pdevicePathName);

HIDUSBAddress.Add(devicePathName);

//index++;

//break;

//}

//连接设备文件

int aa = CT_CreateFile(devicePathName);

bool bb = USBDataRead(HidHandle);

}

//建立和设备的连接

public unsafe int CT_CreateFile(string DeviceName)

{

HidHandle = CreateFile(

DeviceName,

GENERIC_READ,// | GENERIC_WRITE,//读写,或者一起

FILE_SHARE_READ,// | FILE_SHARE_WRITE,//共享读写,或者一起

0,

OPEN_EXISTING,

0,

0);

if (HidHandle == -1)

{

return 0;

}

else

{

return 1;

}

}

//根据CreateFile拿到的设备handle访问文件,并返回数据

public unsafe bool USBDataRead(int handle)

{

while (true)

{

uint read = 0;

//注意字节的长度,我这里写的是8位,其实可以通过API获取具体的长度,这样安全点,

//具体方法我知道,但是没有写,过几天整理完代码,一起给出来

Byte[] m_rd_data = new Byte[8];

bool isread = ReadFile((IntPtr)handle, m_rd_data, (uint)8, ref read, IntPtr.Zero);

//这里已经是拿到的数据了

Byte[] m_rd_dataout = new Byte[read];

Array.Copy(m_rd_data, m_rd_dataout, read);

}

}

OK,如果只是获取USB传过来的数据,这里已经足够了,但是有点要注意,2000和XP如果要获取HID键盘和鼠标的数据,readfile是不行的,;

在Win2000和WinXP下不能用CreateFile+ReadFile/WriteFile的方式来读写标准鼠标和标准键盘的数据,因为它们是系统独占的(Exlusive)。

如果你是其他HID类设备,比如游戏手柄或者自定义HID设备,都可以用上面的方式来收发数据,

怎么访问我暂时也不知道,估计要用它方法,看到有些软件是用截取的手段,估计是用钩子了吧。。

还有获取报文长度的代码,如果不确定报文长度,或者为了驱动适应变化,就用一下代码来确定报文的长度

//获取设备具体信息

[DllImport("hid.dll", SetLastError = true)]

private unsafe static extern int HidP_GetCaps(

int pPHIDP_PREPARSED_DATA,                    // IN PHIDP_PREPARSED_DATA  PreparsedData,

ref HIDP_CAPS myPHIDP_CAPS);                // OUT PHIDP_CAPS  Capabilities

[DllImport("hid.dll", SetLastError = true)]

private unsafe static extern int HidD_GetPreparsedData(

int hObject,                                // IN HANDLE  HidDeviceObject,

ref int pPHIDP_PREPARSED_DATA);

// HIDP_CAPS

[StructLayout(LayoutKind.Sequential)]

public unsafe struct HIDP_CAPS

{

public System.UInt16 Usage;                    // USHORT

public System.UInt16 UsagePage;                // USHORT

public System.UInt16 InputReportByteLength;

public System.UInt16 OutputReportByteLength;

public System.UInt16 FeatureReportByteLength;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]

public System.UInt16[] Reserved;                // USHORT  Reserved[17];

public System.UInt16 NumberLinkCollectionNodes;

public System.UInt16 NumberInputButtonCaps;

public System.UInt16 NumberInputValueCaps;

public System.UInt16 NumberInputDataIndices;

public System.UInt16 NumberOutputButtonCaps;

public System.UInt16 NumberOutputValueCaps;

public System.UInt16 NumberOutputDataIndices;

public System.UInt16 NumberFeatureButtonCaps;

public System.UInt16 NumberFeatureValueCaps;

public System.UInt16 NumberFeatureDataIndices;

}

int reportLength = 8;

//获取设备发送的字节的长度(也有其他信息)

int myPtrToPreparsedData = -1;

int result1 = HidD_GetPreparsedData(handle, ref myPtrToPreparsedData);

HIDP_CAPS myHIDP_CAPS = new HIDP_CAPS();

int result2 = HidP_GetCaps(myPtrToPreparsedData, ref myHIDP_CAPS);

reportLength = myHIDP_CAPS.InputReportByteLength;

再补充点,释放设备资源的时候需要用到

//释放设备的访问

[DllImport("kernel32.dll")]

internal static extern int CloseHandle(int hObject);

//释放设备

[DllImport("setupapi.dll", SetLastError = true)]

internal static extern IntPtr SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

public void Dispost()

{

//释放设备资源(hDevInfo是SetupDiGetClassDevs获取的)

SetupDiDestroyDeviceInfoList(hDevInfo);

//关闭连接(HidHandle是Create的时候获取的)

CloseHandle(HidHandle);

}

ok
了.

时间: 2024-11-05 01:12:15

C# 访问USB(HID)设备的相关文章

C# 访问USB(HID)设备方法 (转)

依次使用一下函数: 1.static public extern void HidD_GetHidGuid (ref System.Guid HidGuid); 获取HID的全局GUID 2.static public extern IntPtr SetupDiGetClassDevs(ref System.Guid ClassGuid, string Enumerator, int hwndParent, int Flags); 获取所有hid句柄 3.static public extern

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

stm32 USB hid设备与PC进行双向数据传输时PC不识别USB设备

stm32 USB hid设备与PC进行双向数据传输时PC不识别USB设备,或者开始时识别,拔出后再插入就没有反应了,就连鼠标U盘也没有反应. 我的问题是,我安装了VMware虚拟机,并进行USB设备的分配,使得虚拟机系统也识别USB设备. 所以,解决问题的办法如下: 在<属性>中选择禁用. 然后把下面的VMware Workstation Server 也禁用了.重启电脑就OK了.

[BLE--HID]USB HID设备类定义

简述 HID设备,即人机交互设备,常见的有鼠标,键盘,游戏手柄,等等.一般有线方式都是通过USB连线连接到机器设备,作为用户输入设备.在蓝牙技术中,HID设备的接入就是无线的了.不过HID的相关定义当然还是一样的,不然设备驱动,兼容等问题都会有很多麻烦了.蓝牙中有HID, HOGP profile,但是只是在蓝牙数据通信上做的规范,HID具体含义相关,还是需要看USB相关的HID文档. USB设备类? USB设备可以在启动时,或者是在之后的连接状态下,都能够被主机进行配置.USB设备种类是非常多

转 关于USB HID报告描述符

原文地址 USB HID报告及报告描述符简介 在USB中,USBHOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等.USB报 告描述符(ReportDescriptor)是HID设备中的一个描述符,它是比较复杂的一个描述符.USBHID设备是通过报告来给传送数据的,报告 有输入报告和输出报告.输入报告是USB设备发送给主机的,例如USB鼠标将鼠标移动和鼠标点击等信息返回给电脑,键盘将按键数据数据返回给电脑等:输出 报告是主机发送在

USB HID报告及报告描述符简介

在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等.USB报告描述符(Report Descriptor)是HID设备中的一个描述符,它是比较复杂的一个描述符.        USB HID设备是通过报告来给传送数据的,报告有输入报告和输出报告.输入报告是USB设备发送给主机的,例如USB鼠标将鼠标移动和鼠标点击等信息返回给电脑,键盘将按键数据数据返回给电脑等:输出报告是主机发送给USB设备的,例如键盘上的数字

Java访问USB设备

最近在用Java访问RDing设备,使用的是Java HID API.使用过程中发现一个问题,由于是嵌入式小白,不知道如何向USB设备发送report.于是想到可以看看自带的软件如何访问USB的.找到了一个叫做Bus Hound的软件.非常小,但是功能很全,可以看到电脑上所有USB设备的通信信息.如下图所示.这样就可以看到控制信息和读入读出信息.

ubuntu下virtualbox 虚拟xp 访问USB设备

 Ubuntu安装虚拟机,实现文件和USB的共享 Ubuntu下virtualbox 虚拟xp 访问USB设备

Chrome OS 更新新版本可让Linux访问USB连接的Android设备

谷歌再次为Chrome OS带来了重大版本更新,使版本号达到了75.本次更新的一大亮点就是允许在Chrome OS上运行的Linux能够识别通过USB方式连接的Android设备,能够让用户使用Linux进行调试等等. Chrome OS 75更新日志: ● 新增功能可以让父母在Chrome OS设备为孩子提供更多的时间● 对儿童账号启用对儿童友好的助理● Linux(Beta)可以访问USB连接的Android设备● 通过实现Android DocumentsProvider APIs,现在F