USB驱动分为两块,一块是USB的bus驱动,这个东西,Linux内核已经做好了,我们可以不管,我们只需要了解它的功能。形象的说,USB的bus驱动相当于铺出一条路来,让所有的信息都可以通过这条USB通道到达该到的地方,这部分工作由usb_core(drivers/usb/usb.c)来完成。当USB设备接到USB控制器接口时,usb_core就检测该设备的一些信息,如生产厂商的ID(VID)和产品的ID(PID),或者是设备所属的class、subclass跟protocol,以便确定应该调用哪一个驱动处理该设备。里面复杂细节我们不用管,我们要做的是另一块工作——usb的设备驱动。也就是说,我们就等着usb_core告诉我们要工作了,我们才工作。
OHCI(Open Host Controller Interface)是支持USB1.1的标准,但它不仅仅是针对USB,还支持其他的一些接口,比如它还支持Apple的火线(Firewire,IEEE 1394)接口。与UHCI相比,OHCI的硬件复杂,硬件做的事情更多,所以实现对应的软件驱动的任务,就相对较简单。主要用于非x86的USB,如扩展卡、嵌入式开发板的USB主控。本文也是基于OHCI来介绍usb设备驱动的。
USB从设备的分类可以从USB设备接口描述符(Standard Interface Descriptor)对应的的bInterfaceClass这一个byte得到。bInterfaceClass的典型代码为1,2,3,6,7,8,9,10,11,255。分别代表的意思为
1-audio:表示一个音频设备。
2-communication device:通讯设备,如电话,moden等等。
3-HID:人机交互设备,如键盘,鼠标等。
6-image图象设备,如扫描仪,摄像头等,有时数码相机也可归到这一类。
7-打印机类。如单向,双向打印机等。
8-mass storage海量存储类。所有带有一定存储功能的都可以归到这一类。
9-hub类。
11-chip card/smart card。
255-vendor specific.厂家的自定义类,主要用于一些特殊的设备。如接口转接卡等。
USB 4种传输方式
针对设备对系统资源需求的不同,在USB规范中规定了4种数据传输方式:
(1)等时传输。该方式用来连接需要连续传输,且对数据的正确性要求不高而对时间极为敏感的外部设备,如麦克风、音响及电话等。等时传输方式以固定的传输速率,连续不断地在主机与USB设备之间传输数据,在传输数据发生错误是,USB并不处理这些错误,而是继续传送信的数据。
(2)中断传输。改方式传输的数据量很小,但这些数据需要及时处理,以达到实时效果,以此方式主要用在键盘、鼠标以及游戏手柄等外部设备上。
(3)控制传输。改方式用来处理主机的USB设备的数据传输。包括设备控制指令、设备状态查询及确认命令。当USB设备收到这些数据和命令后,将依据先进先出的原则按队列方式处理到达的数据。
(4)批量传输、该方式用来传输要求正确无误的数据。通常打印机、扫描仪和数码相机以这种方式与主机连接。
在这4种数据传输方式中,除等时传输方式外,其他3种方式在数据传输发生错误是,都会试图重行发送数据以保证其正确性。
3.USB枚举
枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序。调试USB设备,很重要的一点就是USB的枚举过程,只要枚举成功了,那么就已经成功大半了。
3.1 USB枚举过程概述
USB主机检测到USB设备插入后,就会先对设备复位。设备复位后,USB主机就会对地址为0的设备发送获取设备描述符的标准请求。所有的USB设备在总线复位后其他地址都为0,这样主机可以跟那些刚刚插入的设备通过地址0通信。主机在建立阶段发出获取设备描述符的输入请求,设备受到请求后,将设备描述符返回给主机。主机在成功获取到一个数据包的设备描述符后并且确认没有错误后(有些usb设备的断点0大小不足18字节,但至少有8字节,而标准的设备描述符有18个字节,在这种情况下,USB设备只能暂时按最大包将部分设备描述符返回,而主机在成功获取到前面一部分描述符后,就不会在请求剩下的设备描述符部分,而是进入设置地址阶段),就会返回一个0长度的状态数据包给设备。
然后主机再对设备复位一下,接下来就会静茹到设置地址阶段。这时USB主机发出一个设置地址的请求(建立过程,设置地址无数据过程),地址包含在建立包过程,具体的地址USB主机会负责管理,它会分配一个唯一的地址给新的设备。USB设备在收到地址后,返回0长度的状态包,主机收到0长度的状态包后,会返回一个ACK给设备。设备在收到这个ACK后,就可以启用这个新地址了。这样设备就分配到了一个唯一的设备地址,以后主机就通过它来访问该设备。
然后主机再次获取设备描述符,这次跟第一次可能有点不一样,这次需要获取全部的18个字节的设备描述符。当然,若果你的端点0缓冲大小大于18个自己的话,那就跟第一次的情形一样了。
接下来,主机会获取配置描述符。配置描述符总共为9个字节。主机在获得到配置描述符后,根据里面的配置集合总长度,再获得配置集合。配置集合包括配置描述符,接口描述符,端点描述符等。
如果有字符串描述符的话,还要获取字符串描述符。另外HID设备还有HID描述符等。
USB设备枚举过程主要可分为8个部分:
1、获取设备描述符
2、复位
3、设置地址
4、再次获取设备描述符
5、获取配置描述符
6、获取接口、端点描述符
7、获取字符串描述符
8、选择设备配置
(附3是HP1108打印机插到pc上时通过Bus Hound抓到的枚举过程,可以以作为一个很好的学习例子。)
3.2 USB枚举过程详解
USB协议定义了设备的6种状态,仅在枚举过程中,设备就经历了4个状态的迁移:上电状态(Powered),默认状态(Default),地址状态(Address)和配置状态(Configured)(其他两种是连接状态和挂起状态(Suspend))。
(1)用户把USB设备插入USB端口或系统启动时给设备上电
这里的USB端口指的是主机下的根hub或主机下行端口上的hub端口。Hub给端口供电(hub.c:usb_hub_power_on()),连接着的设备处于上电状态。此时,USB设备处于加电状态,它所连接的端口是无效的。
(2) Hub监测它各个端口数据线上(D+/D-)的电压
在hub端,数据线D+和D-都有一个阻值在14.25k到24.8k的下拉电阻Rpd,而在设备端,D+(全速,高速)和D-(低速)上有一个1.5k的上拉电阻Rpu。当设备插入到hub端口时,有上拉电阻的一根数据线被拉高到幅值的90%的电压(大致是3V)。hub检测到它的一根数据线是高电平,就认为是有设备插入,并能根据是D+还是D-被拉高来判断到底是什么设备(全速/低速)插入端口。检测到设备后,hub继续给设备供电,但并不急于与设备进行USB传输。
USB接口定义如下图所示:
(3)Host了解连接的设备
每个hub利用它自己的中断端点向主机报告它的各个端口的状态(hub.c:usb_hub_events()),报告的内容只是hub端口的设备连接/断开的事件。如果有连接/断开事件发生(hub.c:usb_hub_port_connect_change()),那么host会发送一个 usb_hub_port_status请求给hub以了解此次状态改变的确切含义。usb_hub_port_status等请求属于所有hub都要求支持的hub类标准请求(standard hub-class requests)。
(4) Hub检测所插入的设备是高速还是低速设备
hub通过检测USB总线空闲(Idle)时差分线的高低电压来判断所连接设备的速度类型,当host发来usb_hub_port_status请求时,hub就可以将此设备的速度类型信息回复给host。
(5) hub复位设备
主机一旦得知新设备已连上以后,它至少等待100ms以使得插入操作的完成以及设备电源稳定工作。然后主机控制器就向hub发出一个 usb_set_port_feature请求让hub复位其管理的端口(刚才设备插上的端口)。hub通过驱动数据线到复位状态(D+和D-全为低电平 ),并持续至少10ms。当然,hub不会把这样的复位信号发送给其他已有设备连接的端口,所以其他连在该hub上的设备自然看不到复位信号,不受影响。
(6) Host检测所连接的全速设备是否是支持高速模式
对于USB1.1协议,host不进行高速检测,设备将一直以全速工作。如果是USB 2.0协议,高速(High Speed)设备在初始时是默认全速(Full Speed )状态运行,所以对于一个支持USB 2.0的高速hub,当它发现它的端口连接的是一个全速设备时,会进行高速检测,看看目前这个设备是否还支持高速传输,如果是,那就切到高速信号模式,否则就一直在全速状态下工作。
同样的,从设备的角度来看,如果是一个高速设备,在刚连接bub或上电时只能用全速信号模式运行(根据USB 2.0协议,高速设备必须向下兼容USB 1.1的全速模式)。随后hub会进行高速检测,之后这个设备才会切换到高速模式下工作。
(7) Hub建立设备和主机之间的信息通道
主机通过usb_hub_port_wait_reset不停地向hub发送usb_hub_port_status请求,以查询设备是否复位成功。Hub返回的报告信息中有专门的一位用来标志设备的复位状态。
当hub撤销了复位信号,设备就处于默认/空闲状态(Default state),准备接收主机发来的请求。设备和主机之间的通信通过控制传输,默认地址0,端点号0进行。此时,设备能从总线上得到的最大电流是100mA。(所有的USB设备在总线复位后其地址都为0,这样主机就可以跟那些刚刚插入的设备通过地址0通信。)
(8) 主机发送usb_get_device_descriptor请求获取默认管道的最大包长度
默认管道(Default Pipe)在设备一端来看就是端点0。主机此时发送的请求是默认地址0,端点0,虽然所有未分配地址的设备都是通过地址0来获取主机发来的请求,但由于枚举过程不是多个设备并行处理,而是一次枚举一个设备的方式进行,所以不会发生多个设备同时响应主机发来的请求。
设备描述符(附1)的第8字节(bMaxPacketSize)代表设备端点0的最大包大小。虽然说设备所返回的设备描述符(Device Descriptor)长度只有18字节,但系统也不在乎,此时,描述符的长度信息对它来说是最重要的。当完成第一次的控制传输后,也就是完成控制传输的状态阶段,系统会要求hub对设备进行再一次的复位操作(USB规范里面可没这要求)。再次复位的目的是使设备进入一个确定的状态。
(9) 主机给设备分配一个地址
主机控制器通过usb_set_address请求向设备分配一个唯一的地址。在完成这次传输之后,设备进入地址状态(Address state),之后就启用新地址继续与主机通信。这个地址对于设备来说是终生制的,设备在,地址在;设备消失(被拔出,复位,系统重启),地址被收回。同一个设备当再次被枚举后得到的地址不一定是上次那个了。
(10) 主机获取设备的信息
主机发送 usb_get_device_descriptor请求到新地址读取设备描述符,这次主机发送usb_get_device_descriptor会认真解析设备描述符的内容。设备描述符内信息包括端点0的最大包长度,设备所支持的配置(ConfiguraTIon)个数,设备类型,VID(Vendor ID,由USB-IF分配), PID((Product ID,由厂商自己定制)等信息。Get_Descriptor请求(Device type)和设备描述符(已抹去VID,PID等信息)
之后主机发送usb_get_configuraTIon请求,读取配置描述符(附2),字符串等,逐一了解设备更详细的信息。事实上,对于配置描述符的标准请求中,有时bLength(附2)一项会大于实际配置描述符的长度(9字节),比如255。这样的效果便是:主机发送了一个usb_get_configuraTIon 的请求,设备会把接口描述符,端点描述符等后续描述符一并回给主机,主机则根据描述符头部的标志判断送上来的具体是何种描述符。
接下来,主机就会获取配置描述符。配置描述符总共为9字节。主机在获取到配置描述符后,根据里面的配置集合总长度,再获取配置集合。配置集合包括配置描述符,接口描述符,端点描符等等。
如果有字符串描述符的话,还要获取字符串描述符。另外HID设备还有HID描述符等。
(11) 主机给设备挂载驱动
主机通过解析描述符后对设备有了足够的了解,会通过usb_find_drivers选择一个最合适的驱动给设备。然后tell the world(announce_device)说明设备已经找到了,最后调用设备模型提供的接口usbdevfs_add_device将设备添加到 usb 总线的设备列表里,然后 usb总线会遍历驱动列表usb_driver_list里的每个驱动,调用自己的 usb_match_id 函数看它们和当前连接的设备或接口是否匹配,匹配的话就将控制权交到相应的设备驱动了。
对于复合设备,通常应该是不同的接口(Interface)配置给不同的驱动,因此,需要等到当设备被配置并把接口使能后才可以把驱动挂载上去。
(12) 设备驱动选择一个配置
驱动(注意,这里是驱动,之后的事情都是由驱动来接管负责与设备的通信)根据前面设备回复的信息,发送usb_set_configuraTIon请求来正式确定选择设备的哪个配置(Configuration)作为工作配置(对于大多数设备来说,一般只有一个配置被定义)。至此,设备处于配置状态(Configured),当然,设备也应该使能它的各个接口(Interface)。
对于复合设备,主机会在这个时候根据设备接口信息,给它们挂载驱动。至此,USB枚举过程结束,设备可以正常使用了。
附1 设备描述符结构体
//设备描述符
struct usb_device_descriptor {
__u8 bLength;//端点描述符长度,单位为Byte
__u8 bDescriptorType;//描述符的类型
__le16 bcdUSB;//以bcd码,标出的usb的版本号
__u8 bDeviceClass;//该设备所属的类
__u8 bDeviceSubClass;//该设备所属的子类
__u8 bDeviceProtocol;//该设备所用的协议
__u8 bMaxPacketSize0;//端点0的最大包大小
__le16 idVendor;//厂商id
__le16 idProduct;//产品id
__le16 bcdDevice;//设备版本号
__u8 iManufacturer;//制造商描述符串索引
__u8 iProduct;//产品描述符串索引
__u8 iSerialNumber;//usb串号串索引
__u8 bNumConfigurations;//该设备所拥有的配置个数
} __attribute__ ((packed));
附2 配置描述符结构体
struct usb_config_descriptor {
__u8 bLength;//端点描述符长度,单位为Byte
__u8 bDescriptorType;//描述符的类型
__le16 wTotalLength;//配置描述符的总长度
__u8 bNumInterfaces;//该配置下的接口个数
__u8 bConfigurationValue;//该配置的索引
__u8 iConfiguration;//配置描述符串索引
__u8 bmAttributes;
__u8 bMaxPower;//该配置所能供应的最大电流,以2mA为单位
} __attribute__ ((packed));
附3 BUS HOUND 抓usb打印机HP1108的枚举过程
Bus Hound 5.04capture on Windows XP Service Pack 3. Complements of www.perisoft.net
Device -Device ID (followed by the endpoint for USB devices)
(19)Prolific USB-to-Serial Comm Port (COM2)
(21) USBComposite Device
(22) HPSmart Install [ROM=1.0 ]
(23) USBPrinting Support
(24) P1100USB EWS Device Driver
(25) HPLaserJet Professional P1108
Phase - Phase Type
CMD SCSI/ATAPIcommand RESET bus reset
CTL USB control transfer SENSESCSI sense data
IN Data intransfer USTS USB status
OUT Data outtransfer ok command complete
Data - Hex dump of the data transferred
Descr - Description of the phase
Cmd... - Position in the captured data
Device Phase Data Description Cmd.Phase.Ofs(rep)
------ ----- ------------------------------------------------------------------------------------------------------ ---------------- ------------------
21.0 CTL 80 06 00 03 00 00 ff00 GET DESCRIPTOR 1.1.0(2)
21.0 IN 04 03 0904 .... 1.2.0
21.0 CTL 80 06 02 03 09 04 ff00 GET DESCRIPTOR 2.1.0(2)
21.0 IN 3e 03 48 00 50 00 2000 4c 00 61 00 73 00 65 00 72 00 4a 00 65 00 7400 20 00 50 00 72 00 6f 00 >.H.P..L.a.s.e. 2.2.0
66 00 65 00 73 00 73 00 69 00 6f 00 6e 00 61 00 6c 0020 00 50 00 31 00 31 00 30 00 3800 f.e.s.s.i.o.n.a. 2.2.32
21.0 CTL 80 06 00 01 00 00 1200 GET DESCRIPTOR 5.1.0
21.0 IN 12 01 00 02 00 00 0040 f0 03 2a 00 00 01 01 02 0301 .......@..*..... 5.2.0
21.0 CTL 80 06 00 02 00 00 0900 GET DESCRIPTOR 6.1.0
21.0 IN 09 02 20 00 01 01 00c0 31 .......1 6.2.0
21.0 CTL 80 06 00 02 00 00 2000 GET DESCRIPTOR 7.1.0
21.0 IN 09 02 20 00 01 01 00c0 31 09 04 00 00 02 08 06 50 05 07 05 04 02 0002 00 07 05 84 02 00 02 00 .......1....... 7.2.0
21.0 CTL 80 06 00 03 00 00 0200 GET DESCRIPTOR 8.1.0
21.0 IN 0403 .. 8.2.0
21.0 CTL 80 06 00 03 00 00 0400 GET DESCRIPTOR 9.1.0
21.0 IN 04 03 0904 .... 9.2.0
21.0 CTL 80 06 03 03 09 04 0200 GET DESCRIPTOR 10.1.0
21.0 IN 2a03 *. 10.2.0
21.0 CTL 80 06 03 03 09 04 2a00 GET DESCRIPTOR 11.1.0
21.0 IN 2a 03 30 00 30 00 3000 30 00 30 00 30 00 30 00 30 00 30 00 51 00 3800 37 00 57 00 42 00 50 00 *.0.0.0.0.0.0.0. 11.2.0
52 00 53 00 49 00 31 00 6300 R.S.I.1.c. 11.2.32
21.0 CTL 00 09 01 00 00 00 0000 SETCONFIG 12.1.0
21.0 CTL 01 0b 00 00 00 00 0000 SET INTERFACE 13.1.0
21.0 CTL a1 fe 00 00 00 00 01 00 GET MAX LUN 14.1.0
21.0 IN 00 . 14.2.0
21.4 OUT 55 53 42 43 08 90 9e 89 2400 00 00 80 00 06 12 00 00 00 24 00 00 00 00 00 00 0000 00 00 00 USBC....$....... 15.1.0
21.4 IN 05 80 02 02 1f 00 0000 48 50 20 20 20 20 20 20 53 6d 61 72 74 20 496e 73 74 61 6c 6c 20 20 20 ........HP 16.1.0
31 2e 3020 1.0 16.1.32
21.4 IN 55 53 42 53 08 90 9e89 00 00 00 00 00 USBS......... 17.1.0
22 CMD 12 00 00 00 2400 INQUIRY 18.1.0
22 IN 05 80 02 02 1f 0000 00 48 50 20 20 20 20 20 20 53 6d 61 72 74 20 496e 73 74 61 6c 6c 20 20 20 ........HP 18.2.0
31 2e 3020 1.0 18.2.32
22 CMD 12 00 00 00 2400 INQUIRY 19.1.0(2)
21.4 OUT 55 53 42 43 00 8e ae 8a 2400 00 00 80 00 06 12 00 00 00 24 00 00 00 00 00 00 0000 00 00 00 USBC....$....... 20.1.0(2)
21.4 IN 05 80 02 02 1f 00 0000 48 50 20 20 20 20 20 20 53 6d 61 72 74 20 496e 73 74 61 6c 6c 20 20 20 ........HP 21.1.0(2)
31 2e 3020 1.0 21.1.32
21.4 IN 55 53 42 53 00 8e ae8a 00 00 00 00 00 USBS......... 22.1.0(2)
22 IN 05 80 02 02 1f 0000 00 48 50 20 20 20 20 20 20 53 6d 61 72 74 20 496e 73 74 61 6c 6c 20 20 20 ........HP 19.2.0
31 2e 3020 1.0 19.2.32
22 CMD 25 00 00 00 00 00 0000 0000 READ CAPACITY 27.1.0(2)
21.4 OUT 55 53 42 43 08 90 9e 89 0800 00 00 80 00 0a 25 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 USBC...........% 28.1.0(2)
21.4 USTS 04 00 00c0 stallpid 29.1.0(2)
21.4 RESET 30.1.0(2)
21.4 IN 55 53 42 53 08 90 9e89 08 00 00 00 01 USBS......... 31.1.0(2)
21.4 OUT 55 53 42 43 08 90 9e 89 1200 00 00 80 00 0c 03 00 00 00 12 00 00 00 00 00 00 0000 00 00 00 USBC............ 32.1.0(2)
21.4 IN 70 00 06 00 00 00 000a 00 00 00 00 28 00 00 00 0000 p...........(... 33.1.0(2)
21.4 IN 55 53 42 53 08 90 9e89 00 00 00 00 00 USBS......... 34.1.0(2)
22 SENSE 70 00 06 00 00 00 00 0a 0000 00 00 28 00 00 00 0000 medium changed 27.2.0
22 CMD 4a 01 00 00 00 00 0000 0800 GET EVENT STATUS 43.1.0(2)
21.4 OUT 55 53 42 43 98 16 ae 8a 0800 00 00 80 00 0a 4a 01 00 00 00 00 00 00 08 00 00 0000 00 00 00 USBC...........J 44.1.0(2)
21.4 IN 00 00 00 00 00 00 0000 ........ 45.1.0(2)
21.4 IN 55 53 42 53 98 16 ae8a 00 00 00 00 00 USBS......... 46.1.0(2)
22 IN 00 00 00 00 00 000000 ........ 43.2.0
22 CMD 00 00 00 00 0000 TEST UNIT READY 51.1.0(4)
21.4 OUT 55 53 42 43 08 50 c7 89 0000 00 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 USBC.P.......... 52.1.0(4)
21.4 IN 55 53 42 53 08 50 c789 00 00 00 00 01 USBS.P....... 53.1.0(4)
21.4 OUT 55 53 42 43 08 50 c7 89 1200 00 00 80 00 0c 03 00 00 00 12 00 00 00 00 00 00 0000 00 00 00 USBC.P.......... 54.1.0(4)
21.4 IN 70 00 06 00 00 00 000a 00 00 00 00 28 00 00 00 0000 p...........(... 55.1.0(4)
21.4 IN 55 53 42 53 08 50 c789 00 00 00 00 00 USBS.P....... 56.1.0(4)
22 SENSE 70 00 06 00 00 00 00 0a 0000 00 00 28 00 00 00 0000 medium changed 51.2.0
22 CMD d0 00 00 00 0000 75.1.0
21.4 OUT 55 53 42 43 08 50 c7 89 0000 00 00 00 00 06 d0 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 USBC.P.......... 76.1.0
21.4 IN 55 53 42 53 08 50 c789 00 00 00 00 00 USBS.P....... 77.1.0
22 ok 75.2.0
21.0 CTL 80 06 00 03 00 00 ff00 GET DESCRIPTOR 78.1.0(2)
21.0 IN 04 03 0904 .... 78.2.0
21.0 CTL 80 06 02 03 09 04 ff00 GET DESCRIPTOR 79.1.0(2)
21.0 IN 3e 03 48 00 50 00 2000 4c 00 61 00 73 00 65 00 72 00 4a 00 65 00 7400 20 00 50 00 72 00 6f 00 >.H.P..L.a.s.e. 79.2.0
66 00 65 00 73 00 73 00 69 00 6f 00 6e 00 61 00 6c 0020 00 50 00 31 00 31 00 30 00 3800 f.e.s.s.i.o.n.a. 79.2.32
21.0 CTL 80 06 00 01 00 00 1200 GET DESCRIPTOR 82.1.0
21.0 IN 12 01 00 02 00 00 0040 f0 03 2a 00 00 01 01 02 0301 .......@..*..... 82.2.0
21.0 CTL 80 06 00 02 00 00 0900 GET DESCRIPTOR 83.1.0
21.0 IN 09 02 3e 00 02 01 00c0 31 ..>.....1 83.2.0
21.0 CTL 80 06 00 02 00 00 3e00 GET DESCRIPTOR 84.1.0
21.0 IN 09 02 3e 00 02 01 00c0 31 09 04 00 00 02 07 01 02 04 07 05 01 02 0002 00 07 05 81 02 00 02 00 ..>.....1....... 84.2.0
09 04 01 00 03 ff 02 10 06 07 05 02 02 00 02 00 07 0582 02 00 02 00 07 05 83 03 08 000c ................ 84.2.32
21.0 CTL 00 09 01 00 00 00 0000 SETCONFIG 85.1.0
21.0 CTL 80 06 04 03 09 04 ff00 GET DESCRIPTOR 86.1.0
21.0 IN 10 03 50 00 72 00 6900 6e 00 74 00 65 00 7200 ..P.r.i.n.t.e.r. 86.2.0
21.0 CTL 80 06 06 03 09 04 ff00 GET DESCRIPTOR 87.1.0
21.0 IN 0e 03 48 00 50 00 2000 45 00 57 00 5300 ..H.P. .E.W.S. 87.2.0
23.0 CTL 80 06 00 02 00 00 0901 GET DESCRIPTOR 88.1.0
23.0 IN 09 02 20 00 01 01 00c0 31 09 04 00 00 02 07 01 02 04 07 05 01 02 0002 00 07 05 81 02 00 02 00 .. .....1....... 88.2.0
23.0 CTL 00 09 01 00 00 00 0000 SETCONFIG 89.1.0
23.0 CTL 80 06 00 01 00 00 1200 GET DESCRIPTOR 90.1.0
23.0 IN 12 01 00 02 00 00 0040 f0 03 2a 00 00 01 01 04 0301 .......@..*..... 90.2.0
23.0 CTL a1 00 00 00 00 00 f103 GET DEVICE ID 91.1.0
23.0 IN 00 8c 4d 46 47 3a 4865 77 6c 65 74 74 2d 50 61 63 6b 61 72 64 3b 4d44 4c 3a 48 50 20 4c 61 73 ..MFG:Hewlett-Pa 91.2.0
65 72 4a 65 74 20 50 72 6f 66 65 73 73 69 6f 6e 61 6c20 50 31 31 30 38 3b 43 4d 44 3a 5a 4a 53 erJetProfession 91.2.32
2c 50 4a 4c 2c 41 43 4c 2c 48 54 54 50 3b 43 4c 53 3a50 52 49 4e 54 45 52 3b 44 45 53 3a 48 50 ,PJL,ACL,HTTP;CL 91.2.64
20 4c 61 73 65 72 4a 65 74 20 50 72 6f 66 65 73 73 696f 6e 61 6c 20 50 31 31 30 38 3b 46 57 56 LaserJet Profes 91.2.96
45 52 3a 32 30 31 32 30 38 31 343b ER:20120814; 91.2.128
24.0 CTL 80 06 00 01 00 00 1200 GET DESCRIPTOR 92.1.0
24.0 IN 12 01 00 02 00 00 0040 f0 03 2a 00 00 01 01 06 0301 .......@..*..... 92.2.0
24.0 CTL 80 06 00 02 00 00 0900 GET DESCRIPTOR 93.1.0
24.0 IN 09 02 27 00 01 01 00c0 31 ..'.....1 93.2.0
24.0 CTL 80 06 00 02 00 00 2700 GET DESCRIPTOR 94.1.0
24.0 IN 09 02 27 00 01 01 00c0 31 09 04 01 00 03 ff 02 10 06 07 05 02 02 0002 00 07 05 82 02 00 02 00 ..'.....1....... 94.2.0
07 05 83 03 08 000c ....... 94.2.32
24.0 CTL 80 00 00 00 00 00 0200 GETSTATUS 95.1.0
24.0 IN 0100 .. 95.2.0
24.0 CTL 00 09 01 00 00 00 0000 SETCONFIG 96.1.0
21.0 CTL 01 0b 00 00 01 00 0000 SET INTERFACE 97.1.0
21.0 CTL 80 06 00 02 00 00 3e00 GET DESCRIPTOR 98.1.0
21.0 IN 09 02 20 00 01 01 00c0 31 09 04 00 00 02 08 06 50 05 07 05 04 02 0002 00 07 05 84 02 00 02 00 .......1....... 98.2.0