Windows,Linux,Mac系统中,USB HID枚举过程的异同 您所在的位置:网站首页 mac系统和linux系统 Windows,Linux,Mac系统中,USB HID枚举过程的异同

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

2023-08-31 10:39| 来源: 网络整理| 查看: 265

http://www.crifan.com/order_windows_linux_mac_systems_usb_hid_similarities_and_differences_between_the_enumeration_process/

【整理】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  http://www.cygnal.org/ubb/Forum9/HTML/001325.html  简单来说,就是,不同的操作系统,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  http://www.cygnal.org/ubb/Forum9/HTML/001325.html  进行简单翻译如下,以对不同系统中,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 len  RESET | RESET | RESET  GET_DESCRIPTOR DEVICE 0100 0000 64 | GET_DESCRIPTOR DEVICE 0100 0000 64 | GET_DESCRIPTOR DEVICE 0100 0000 8  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 10  GET_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



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有