Windows下读取USB Hid设备数据的经验总结

来源:互联网 发布:sql同一班级的成绩降序 编辑:程序博客网 时间:2024/04/30 00:18

       接上一篇文档,PC机下的USB通讯项目进入到了读取Hid设备数据的阶段。在这里遇到了两个问题,解决这两个问题从中得到了三个经验,在这里列出供大家分享。

        1.ReadFile()总是返回false的问题:

        ReadFile()读取之前已打开的设备文件,总是返回false,没有一次成功的情况。看网上例程也确实是这样写,没有什么不同。通过在C#程序中调用Marshal.GetLastWin32Error()查看错误值,为1784。网上查找此问题的解决办法,找到了一个非常好的网址:

http://blog.csdn.net/phenixyf/article/details/39929033

其中有这样一段内容:

3IN_REPORT_LEN代表要读取的数据的长度(实际的数据正文+一个byte的报告ID),这里是一个常数,主要是由于设备固件的信息我是完全知道的,当然知道要读取多少数据(也就是报告的长度);不过也可以通过另外的函数(HidD_GetPreparsedData)来事先取得报告的长度,这里不做具体讨论。由于很难想象在不了解固件信息的情况下来做自定义设备的HID通讯,在实际应用中一般来说就是固件与PC程序匹配着来开发。此参数假如设置过大,不会有实质性的错误,在recvBytes参数中会输出实际读到的长度;假如设置过小,即小于报告的长度,会返回1784号错误(用户提供的buffer无效)。

       通过以上内容,分析应该是ReadFile()中传入的要读取数据的长度设置的太小,将此数据设得比较大,再次运行程序,这次 ReadFile()可以正确返回数据了!

 

       经验一: ReadFile()时要读取的数据长度尽量设置大一些(当然,这只是针对没有通过函数获得设备发来数据的情况)。

 

       在此基础上观察实际返回的读到数据的长度,发现大多数情况下第一次返回65(下位机每帧发64个字节数据),以后都返回2080,为何总是2080

       在网上查找此问题的解释,还是找到了上面的那篇文章,有这样一内容:

1ReadFile的调用不会引起设备的任何反应,即 HID设备与主机之间的中断 IN传输不与 ReadFile打交道。实际上主机会在最大间隔时间(由设备的端点描述符来指定)内轮询设备,发出中断 IN传输的请求。读取即意味着从某个buffer里面取回数据,实际上这个 buffer就是HID设备驱动中的 buffer。这个buffer的大小可以通过 HidD_SetNumInputBuffers来改变。在XP上缺省值是 32(个报告)。
       又从微软官方说明网站:https://msdn.microsoft.com/en-us/library/windows/hardware/ff539686(v=vs.85).aspx中得到了确认:

IfHidD_SetNumInputBuffers returnsFALSE, and the Microsoft Win32GetLastError function indicates thatan invalid parameter was supplied, the value of NumberBuffers is invalid. The HID classdriver requires a minimum of two input buffers. On Windows 2000, the maximumnumber of input buffers that the HID class driver supports is 200, and onWindows XP and later, the maximum number of input buffers that the HID classdriver supports is 512. The default number of input buffers is 32.

 

       这里65*32 = 2080。在程序中加入HidD_SetNumInputBuffers()进行测试,所得结果与说明完全一致(设为16时,得到65*16 = 1040;设为2时,得到65*2= 130;设为1时,又回到了65*32= 2080)。

        经验二:可以通过HidD_SetNumInputBuffers()改变得到的数据的长度。

 

         2.为何每帧的长度为65而非64

       通过上边的内容,可以看到,下位机每次发送64字节,为何这里每一帧的长度为65?为何在一帧数据的前边多了一个0x00?

       

       其实这个问题上面已经说得很清楚了,3IN_REPORT_LEN代表要读取的数据的长度(实际的数据正文+一个byte的报告ID),多了一个字节的报告ID.每次收到数据后将这个字节过滤掉就可以了。

经验三:返回的长度会比实际发送的长度每帧多一个字节的报告ID

其实还应该有一个经验四:与其在网上有病乱投医,不如仔细阅读官网上的资料,那是最准确最详实的!

 



 


0 0
原创粉丝点击