Windows,Linux,Mac系统中,USB HID枚举过程的异同 | 您所在的位置:网站首页 › mac系统和linux系统 › Windows,Linux,Mac系统中,USB HID枚举过程的异同 |
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 实验室设备网 版权所有 |