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 = ; // dumy
public int reserved = ;
} [StructLayout(LayoutKind.Sequential, Pack = )]
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 = -;
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 = ; private void UsBMethod(int index)
{
HidD_GetHidGuid(ref guidHID);
hDevInfo = SetupDiGetClassDevs(ref guidHID, , IntPtr.Zero, DIGCF.DIGCF_PRESENT | DIGCF.DIGCF_DEVICEINTERFACE);
int bufferSize = ;
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, , 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 + );
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,//共享读写,或者一起
,
OPEN_EXISTING,
,
);
if (HidHandle == -)
{
return ;
}
else
{
return ;
}
}
//根据CreateFile拿到的设备handle访问文件,并返回数据
public unsafe bool USBDataRead(int handle)
{
while (true)
{
uint read = ;
//注意字节的长度,我这里写的是8位,其实可以通过API获取具体的长度,这样安全点,
//具体方法我知道,但是没有写,过几天整理完代码,一起给出来
Byte[] m_rd_data = new Byte[];
bool isread = ReadFile((IntPtr)handle, m_rd_data, (uint), 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 = )]
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 = ;
//获取设备发送的字节的长度(也有其他信息)
int myPtrToPreparsedData = -;
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
了.
C# 访问USB(HID)设备的更多相关文章
- Windows与自定义USB HID设备通信说明.
1 . 所使用的典型 Windows API CreateFile ReadFile WriteFile 以下函数是 DDK 的内容: HidD_SetFeature HidD_GetFeatur ...
- android usb Host模式下与usb Hid 设备的通信
做android 与USB HID设备的通信有段时间了,总结一下遇到的问题和解决方法: 1,第一次遇到的问题:android 版本低不支持usb hid, 被要求做相关项目的时候,就从mUsbMana ...
- USB HID设备报告描述符详解(转)
转自:http://group.ednchina.com/93/198.aspx. 参考:USB HID usage table 概述: 报告在这里意思是数据传输(data transfer),而 ...
- Android USB Host 与 Hid 设备通信bulkTransfer()返回-1问题的原因
近期一直在做Android USB Host 与USB Hid设备(STM32FXXX)的通信,遇到了很多问题.项目源码以及所遇到的其他问题可以见本博客其他相关文章,这里重点讲一下bulkTransf ...
- STC8H开发(九): STC8H8K64U模拟USB HID外设
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- USB HID 协议入门
转载请注明来源:cuixiaolei的技术博客 USB HID设备类的应用场合 USB HID类是USB设备的一个标准设备类,包括的设备非常多.HID类设备定义它属于人机交互操作的设备,用于控制计算机 ...
- USB HID报告及报告描述符简介
在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等.USB报告描述符(Report Descriptor)是HID ...
- 第五章 HID设备
5.1 HID介绍 为简化USB设备的开发过程,USB提出了设备类的概念.所有设备类都必须支持标准USB描述符和标准USB设备请求.如果有必要,设备类还可以自行定义其专用的描述符和设备请求,这分别被称 ...
- USB HID Report Descriptor 报告描述符详解
Report descriptors are composed of pieces of information. Each piece of information is called an Ite ...
随机推荐
- Bootstrap入门五:表格
table样式: .table:表格基本样式,很少的padding,灰色的细水平分隔线. .table-striped:斑马纹样式,隔行换色. .table-bordered:为表格和其中的每个单元格 ...
- Careercup - Microsoft面试题 - 5684901156225024
2014-05-10 23:45 题目链接 原题: Arrange the numbers in an array in alternating order. For example if the a ...
- django Forgienkey字段 在前台用js做处理
在我做的项目中有个选择省城市的选项,这两个字段的关系是一对多的关系class Province(models.Model): # 省会 name = models.CharField(max ...
- modernizr.js
1.判断浏览器是否支持 h5 if(Modernizr.canvas){ alert(123); }else{ alert(321); } 2.判断浏览器是否支持 canvas function su ...
- 通过Log4j的DEBUG级别来显示mybatis的sql语句
为了更加方便调试sql语句,需要显示mybatis的sql语句. 网络上的一般方式都是通过log4j来实现,但是很多都有问题. 经过实验,以下代码能够保持正常:(只显示myb ...
- hdu 3487 Play with Chain
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 YaoYao is fond of playing his chains. He has a c ...
- 【BZOJ】【2765】【JLOI2010】铁人双项比赛
计算几何/半平面交 本来我是想去写POJ 1755的,然后想起了这道跟它很像的题,但应该是弱化版,所以就先写了这个…… 我们可以发现每个人的总用时,与k是呈一次函数关系的:$time_i=\frac{ ...
- bootstrap学习记录(慕课网教程)
1.当主标题下需要副标题时可在h中嵌套small<h1>nihao<small>a</samll></h1> 2.当某一段落需要突出显示时可添加lead ...
- The life of an HTML HTTP request
https://developer.mozilla.org/en-US/docs/The_life_of_an_HTML_HTTP_request http://www.html5rocks.com/ ...
- HTTP状态码一览表(HTTP Status Code)
copy from:http://www.189works.com/article-43064-1.html 1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代码. 代码 说明 100 ( ...