linux hid 输入设备 在window上需要额外驱动?,Windows,Linux,Mac系统中,USB HID枚举过程的异同...

【整理】Windows,Linux,Mac系统中,USB HID枚举过程的异同

【背景】

遇到一个问题,即一个设备,用的Silicon的C8051F347的MCU,其中的USB的驱动的HID部分,在Hid_Class_Request函数中,

把GET_REPORT对应的代码,注释掉了,即没有实现对应的GET_REPORT的功能。

由此,导致设备连接到某台Linux PC中,设备无法响应HID的GET_REPORT,因此无法正常工作。

此问题,已经被别人debug后,找到此处代码的原因了。

而我此处的疑问是,经过查找代码修改的历史记录,发现最原始的代码,是实现了GET_REPORT部分的功能的,但是却在后来某个版本注释掉了此部分代码。

所以很是困惑,为何代码作者会注释掉此部分的代码,因为,看起来,USB的HID的spec:

HID1_11 – USB Device Class Definition for Human Interface Devices(HID).pdf

中,

是有说明的:

7.2.1 Get_Report Request

The Get_Report request allows the host to receive a report via the Control pipe.

没有说明是可选的,就说明此功能,是必须支持的。意味着,按照HID的spec来说,代码中,必须要实现此功能的。

【解决过程】

后来去网上找了版本,最后终于找到有人解释的很清楚了:

Difference on HID enumeration on Win, Linux and Mac

简单来说,就是,不同的操作系统,USB HID枚举时候的做法,都不太相同。

而对于此处的问题来说,就是:

Windows中对于USB HID的枚举,不会发送GET_REPOR给设备,即用不到GET_REPOR,所以设备端的驱动,可以不实现此功能;

而Linux中对于USB HID的枚举,会发送GET_REPOR去获取Input的内容,所以设备端的驱动,必须要实现此功能。

其中,Linux的做法,是符合USB的HID的规范的。

但是,现实就是现实,由于Windows的用户足够多,所以,很多驱动开发者,往往就默认地接受了Windows的很多做法,

导致其功能的实现,是按照Windows的做法,而不是协议规范的做法。

【总结】

借用上面那个帖子中所说的,以后写驱动的话,对于USB的特定的枚举过程或顺序,不能完全指望协议,即,也要了解现实世界的做法,即Linux,Windows,Mac中,USB

HID的枚举过程,是不太一样的,作为驱动开发者,最好都要清楚,然后尽可能地都支持这些系统。

下面对

Difference on HID enumeration on Win, Linux and Mac

进行简单翻译如下,以对不同系统中,USB HID枚举过程的异同做出一些总结:

【Windows,Linux,Mac系统中,USB HID枚举过程的异同】

对于不同的OS之间,枚举顺序的不同,下面以SiLabs HID/Blinky(vendor specific HID设备)为例,一一列出来:

注意,此处列出来的,只是设备连接到PC上之后,PC端的程序还没有运行期间的设备枚举的过程。

1. 总线重置(Bus Reset)

WinXp和Linux都会reset两次。

2. Get_Descriptor( Device ) and Get_Descriptor( Config )

WinXP会发送两次Get_Descriptor

3. SET_IDLE

WinXP是在SET_CONFIGURATION之后,发送SET_IDLE

4. interrupt IN/ GET_REPORT

WinXP和Mac OS,使用中断输入端点(interrupt IN EP)发送IN传输(IN transfer),然后继续执行,而忽略主机端程序。

而Linux发送GET_REPORT( input ),且在主机端程序开始运行之前,不会向发送中断端点( interrupt EP)发送IN传输

上述中,最主要的区别,不是枚举过程的顺序本身,而是枚举之后的interrupt IN/ GET_REPORT。

而虽然USB HID的规范中,已经说明了GET_REPORT(input) 是必须支持的一个功能,但是由于WinXP在枚举期间,不发送GET_REPORT(input),

所以实际上,驱动实现者,常常都不去实现此GET_REPORT(input)的功能。

同时,要注意的是,由于Linux在主机端程序运行之前,是不会向中断端点(interrput EP)发送IN请求(IN request

)的,所以,固件(firmware)端,如果期望的是Host端是周期性地会发送请求到中断端点(IN EP)的话,那么程序就会出错了。

即,USB设备端的程序开发者,在写USB驱动程序的时候,要知道上面那些特殊情况,即Host端,即如果是PC端运行的是Linux系统的话,那么在Linux系统程序执行之前,

USB设备端的IN

EP,是收不到对应的IN请求的,这点,写驱动的时候,要自己注意,不能自己假定,设备端,会周期性地,从Host端收到IN请求,如果你是按照这样的逻辑实现的驱动,那么遇到Host端运行的是Linux系统的话,由于收不到对应IN请求,所以程序就不是按照你所期望的去运行了,就出错了。

注:原帖有各个OS中枚举过程的详细的列表对比,现粘贴如下,如果格式很乱,就自己去看格式清晰的:

WinXP sp2 | Linux Kernel 2.6.19 | MacOSX 10.4.9-10.4.10

value index len | value index len | value index lenRESET

| RESET | RESET

GET_DESCRIPTOR DEVICE 0100 0000 64 | GET_DESCRIPTOR DEVICE 0100 0000 64 | GET_DESCRIPTOR DEVICE 0100 00008

RESET | RESET |SET_ADDRESS

0002 0000 0 | SET_ADDRESS 0003 0000 0 | SET_ADDRESS 0003 0000 0

GET_DESCRIPTOR DEVICE 0100 0000 18 | GET_DESCRIPTOR DEVICE 0100 0000 18 | GET_DESCRIPTOR DEVICE 0100 0000 18

| | GET_DESCRIPTOR STRING 0302 0409 2

| | GET_DESCRIPTOR STRING 0302 0409 10

| | GET_DESCRIPTOR STRING 0301 0409 2

| | GET_DESCRIPTOR STRING 0301 0409 10GET_DESCRIPTOR

CONFIG 0200 0000 9 | GET_DESCRIPTOR CONFIG 0200 0000 9 | GET_DESCRIPTOR CONFIG 0200 0000 4

GET_DESCRIPTOR CONFIG 0200 0000 255 | GET_DESCRIPTOR CONFIG 0200 0000 34 | GET_DESCRIPTOR CONFIG 0200 0000 34

GET_DESCRIPTOR STRING 0300 0000 255 | GET_DESCRIPTOR STRING 0300 0000 255 |

GET_DESCRIPTOR STRING 0302 0409 255 | GET_DESCRIPTOR STRING 0302 0409 255 |

GET_DESCRIPTOR STRING 0300 0000 255 | GET_DESCRIPTOR STRING 0301 0409 255 |

GET_DESCRIPTOR STRING 0302 0409 255 | |

GET_DESCRIPTOR DEVICE 0100 0000 18 | |

GET_DESCRIPTOR CONFIG 0200 0000 9 | |

GET_DESCRIPTOR CONFIG 0200 0000 34 | |

SET_CONFIGURATION 0001 0000 0 | SET_CONFIGURATION 0001 0000 0 | SET_CONFIGURATION 0001 0000 0

SET_IDLE 0000 0000 0 | |

GET_DESCRIPTOR HID REP 2200 0000 147 | GET_DESCRIPTOR HID REP 2200 0000 83 | GET_DESCRIPTOR HID REP 2200 0000 83

| | GET_DESCRIPTOR STRING 0301 0409 2

| | GET_DESCRIPTOR STRING 0301 0409 10

| | GET_DESCRIPTOR STRING 0302 0409 2

| | GET_DESCRIPTOR STRING 0302 0409 10

IN EP=81 | GET_REPORT 0104 0000 2 | IN EP=81

IN EP=81 | GET_REPORT 0105 0000 3 | IN EP=81

SOF IN/NAK | SOF | SOF IN/NAK

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值