参考网站
https://www.usb.org/about
https://github.com/tmk/tmk_keyboard/wiki/HID-Report-Descriptor
https://www.usb.org/document-library/hid-descriptor-tool
参考资料:
Device Class Definition.pdf
dt2_4
HID Usage Tables.pdf
hid1_11.pdf
Usbgeneralpage.pdf
usb_20.pdf
圈圈教你玩USB.pdf
参考工具
USB抓包工具Bus Hound 6.0.1带注册码 使用说明(最新的)\USB抓包工具Bus Hound 6.0.1带注册码+使用说明(最新的)\BusHound+v6.0.1
标准的usb设备请求命令
设备请求命令的格式:
bmRequestType bRequest wValue wIndex wLength
0 bmRequestType 1 Bitmap Characteristics of request:
D7: Data transfer direction
0 = Host-to-device
1 = Device-to-host
D6...5: Type
0 = Standard
1 = Class
2 = Vendor
3 = Reserved
D4...0: Recipient
0 = Device
1 = Interface
2 = Endpoint
3 = Other
4...31 = Reserved
1 bRequest 1
Specific request
2 wValue 2
Word-sized field that varies according to request
4 wIndex 2
Word-sized field that varies according to request; typically used to pass an index or offset
6 wLength 2
Number of bytes to transfer if there is a Data stage
关于bRequest 字段,此字段可以如下
GET_STATUS 0
CLEAR_FEATURE 1
Reserved for future use 2
SET_FEATURE 3
Reserved for future use 4
SET_ADDRESS 5
GET_DESCRIPTOR 6
SET_DESCRIPTOR 7
GET_CONFIGURATION 8
SET_CONFIGURATION 9
GET_INTERFACE 10
SET_INTERFACE 11
SYNCH_FRAME 12
BUS Hound
CTL:表示8字节的USB控制传输的Setup包
bmRequestType —— 80:数据方向从USB到PC;标准的请求;USB设备接收
bRequest —— 06:表示接下来发送的数据时GET_DESCRIPTOR(主控器读取USB描述符)
wValue —— 00 01:从偏移地址0开始读取设备描述符
wIndex —— 00 00:一般用于说明端点号或者接口标识
wLength —— 12 00:下一阶段发送数据的长度为18个字节(小端格式理解)
First 【IN】:数据传输(USB设备到PC)
bLength —— 12:数据字节长度为18
USB描述符信息包括设备描述符、配置描述符、接口描述符和端点描述符
USB区分描述符种类如下:
DEVICE 1
CONFIGURATION 2
STRING 3
INTERFACE 4
ENDPOINT 5
DEVICE_QUALIFIER 6
OTHER_SPEED_CONFIGRATION 7
INTERFACE_POWER 8
上述值会存在各描述符的 bDescriptorType 中以上述值区分当前描述符
如:
设备描述符结构体定义如下
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 bcdUSB;
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
__u8 bMaxPacketSize0;
__le16 idVendor;
__le16 idProduct;
__le16 bcdDevice;
__u8 iManufacturer;
__u8 iProduct;
__u8 iSerialNumber;
__u8 bNumConfigurations;
} __attribute__ ((packed));
对于设备描述符:
bLength:设备描述符的长度为18个字节
bDescriptorType: 设备描述符的类型为0x01。
bcdUSB: USB设备所遵循的协议版本号,例如2.0协议为0x0200。
bDeviceClass: USB设备类代码,由USB-IF分配,如果该字段为0x00,表示由接口描述符来指定(有可能该USB设备是一个复合设备,USB设备的各个接口相互独立,分别属于不同的设备类)。如果是0x01~0xfe,表示为USB-IF定义的设备类,例如0x03为HID设备,0x09为HUB设备。如果是0xff,表示由厂商自定义设备类型。
bDeviceSubClass: USB子类代码,由USB-IF分配,如果bDeviceClass为0x00,那么该字段也必须为 0x00,其它情况可以参考USB关于对于USB Device Class的定义。
bDeviceProtocol: 协议代码,由USB-IF分配,如果bDeviceClass和bDeviceSubClass定义为0x00,那么该字段也必须为0x00
bMaxPacketSize0: 端点0最大数据包长度,必须为8、16、32和64。
idVendor: 厂商ID,由USB-IF分配,需要向USB-IF组织申请。
idProduct: 产品ID,由厂商指定。
bcdDevice: 设备序列号,由厂商自行设置。
iManufacturer: 用于描述厂商的字符串描述符索引。
iProduct: 用于描述产品的字符串描述符索引。
iSerialNumber: 用于描述产品序列号的字符串描述符索引,注意,所有的字符串描述符是可选的,如果没有字符串描述符,指定这些索引为0x00。
bNumConfigurations:配置描述符数量。
对于配置描述符:
配置描述符的数量由bNumConfigurations 字段决定
struct usb_config_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 wTotalLength;
__u8 bNumInterfaces;
__u8 bConfigurationValue;
__u8 iConfiguration;
__u8 bmAttributes;
__u8 bMaxPower;
} __attribute__ ((packed));
bLength: 配置描述符长度,配置描述符长度固定为9字节。
bDescriptorType: 描述符类型,配置描述符类型为0x02。
wTotalLength: 配置描述符信息总字节大小,包括接口描述符、端点描述符等等。
bNumInterfaces: USB接口数量。
bConfigurationValue: 当使用SetConfiguration和GetConfiguration请求时所指定的配置索引值。
iConfiguration: 描述配置的字符串描述符索引。
bmAttributes: 供电配置,位详细定义如下:
D7 保留,必须置1
D6 自供电模式
D5 远程唤醒
D4~D0 保留
bMaxPower: 最大功耗,以2mA为单位
对于接口描述符:
struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bInterfaceNumber;
__u8 bAlternateSetting;
__u8 bNumEndpoints;
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
__u8 iInterface;
} __attribute__ ((packed));
bLength: 描述符长度,接口描述符长度为9个字节。
bDescriptorType: 描述符类型,接口描述符的类型为0x04。
bInterfaceNumber: 该接口编号,接口编号从0开始分配,当一个配置有多个接口时,就用该字段来区分不同的接口。
bAlternateSetting: 设置USB替代模式的值,取决于接口描述符数量
bNumEndpoints: 端点数量,不包括端点0。
bInterfaceClass:03 代表 HID
If this field is set to FFH, the interface class is vendor-specific.
bInterfaceSubClass:Subclass code.
0 No subclass
1 Boot Interface subclass
bInterfaceProtocol:
0 None
1 Keyboard
2 Mouse
iInterface: Index of string descriptor describing this interface
对于端点描述符
注意,端点0没有端点描述符
struct usb_endpoint_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bEndpointAddress;
__u8 bmAttributes;
__le16 wMaxPacketSize;
__u8 bInterval;
__u8 bRefresh;
__u8 bSynchAddress;
} __attribute__ ((packed));
bLength: 描述符长度,如果是audio设备的端点,那么端点描述符长度就为9个字节,对于其它设备端点,端点描述符长度就为7个字节
bDescriptorType: 描述符类型,端点描述符类型为0x05。
bEndpointAddress: 端点地址,详细定义如下:
D7 端点方向
0 OUT端点
1 IN端点
D6~D4 保留
D3~D0 端点编号
bmAttributes :端点类型
D1~D0 Transfer type:
00 Control
01 Isochronous
10 Bulk
11 Interrupt
D3~D2 同步类型
00 非同步
01 异步
10 自适应
11 同步
D5~D4 用途
00 数据端点
01 反馈端点
10 隐式反馈数据端点
11 保留
如果该端点不是同步端点,D5~D2保留且必须置0。
wMaxPacketSize: 端点所支持最大数据包的长度,详细定义如下:
D10~D0 最大数据包长度
D12~D11
其余位保留且必须置0。
bInterval:端点数据传输的访问时间间隔 对于全速/低速的中断端点,取值范围为 1~255,对于高速中断端点,取值范围为1~16,详细定义可以参考USB协议。
对于HID描述符:
struct hid_class_descriptor {
__u8 bDescriptorType;
__le16 wDescriptorLength;
} __attribute__ ((packed));
struct hid_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__le16 bcdHID;
__u8 bCountryCode;
__u8 bNumDescriptors;
struct hid_class_descriptor desc[1];
} __attribute__ ((packed));
bLength: 描述符长度
bDescriptorType:描述符类型,HID描述符的类型为0x21。
bcdHID: 所遵循的HID协议版本。
bCountryCode: 国家代码。
bNumDescriptors: 下级描述符数量,通常至少需要一个报告描述符。
bDescriptorType: 下级描述符类型,例如报告描述符。
wDescriptorLength: 下级描述符长度。一般是报告描述符
对于报告描述符:
setup命令: 81 06 0021 0100 9600 21是hid描述符
81 06 0022 0100 9600 22是report描述符
Usage Pages
00 Undefined
01 Generic Desktop Controls
02 Simulation Controls
03 VR Controls
04 Sport Controls
05 Game Controls
06 Generic Device Controls
07 Keyboard/Keypad
08 LEDs
09 Button
0A Ordinal
0B Telephony
0C Consumer
0D Digitizer
0E Reserved
0F PID Page
10 Unicode
11-13 Reserved
14 Alphanumeric Display
15-3f Reserved
40 Medical Instruments
41-7F Reserved
80-83 Monitor pages
84-87 Power pages
88-8B Reserved
8C Bar Code Scanner page
8D Scale page
8E Magnetic Stripe Reading (MSR)
Devices
8F Reserved Point of Sale pages
每个数据组成由:第一个字节为控制条目,第二个以及以后的字节为数据
解析第一个字节如下:
bSize Numeric expression specifying size of data:
0 = 0 bytes
1 = 1 byte
2 = 2 bytes
3 = 4 bytes
bType Numeric expression identifying type of item where:
0 = Main
1 = Global
2 = Local
3 = Reserved
bTag Numeric expression specifying the function of the item.
[data] Optional data.
举个例子:
05 01 Usage Page (1: Generic Desktop)
09 05 Usage (5: Game Pad )
a1 01 集合开始(Application)
a1 00 集合开始(Physical)
09 30 Usage(X)
09 31 Usage(Y)
15 00 LOGICAL_MINIMUN
26 ff ff LOGICAL_MAXIMUN
35 00 PHYSICAL_MINIMUN
46 ff ff PHYSICAL_MAXIMUN
95 02 REPORT_COUNT
75 10 REPORT_SIZE
81 02 INPUT
c0 END_COLLECTION
a1 00 COLLECTION Physical
09 33 Rx
09 34 Ry
15 00 LOGICAL_MINIMUN
26 ff ff LOGICAL_MAXIMUN
35 00 PHYSICAL_MINIMUN
46 ff ff PHYSICAL_MAXIMUN
95 02 REPORT_COUNT
75 10 REPORT_SIZE
81 02 INPUT
c0 END_COLLECTION
a1 00 COLLECTION Physical
09 32 Z
15 00 LOGICAL_MINIMUN
26 ff ff LOGICAL_MAXIMUN
35 00 PHYSICAL_MINIMUN
46 ff ff PHYSICAL_MAXIMUN
95 01 REPORT_COUNT
75 10 REPORT_SIZE
81 02 INPUT
c0 END_COLLECTION
05 09 Usage Page(Buttion)
19 01 USAGE_MINMUN
29 0a USAGE_MAXMUN
95 0a REPORT_COUNT
75 01 REPORT_SIZE
81 02 INPUT
05 01 Usage Page (1: Generic Desktop)
09 39 USAGE(Hat switch)
15 01 LOGICAL_MINIMUN
25 08 LOGICAL_MAXIMUN
35 00 PHYSICAL_MINIMUN
46 3b 10 PHYSICAL_MAXIMUN
66 0e 00 UNIT
75 04 REPORT_SIZE
95 01 REPORT_COUNT
81 42 INPUT
75 02 REPORT_SIZE
95 01 REPORT_COUNT
81 03 INPUT
75 08 REPORT_SIZE
95 02 REPORT_COUNT
81 03 INPUT
c0 END_COLLECTION
05 01 全局条目,Generic Desktop
09 05 Usage (5: Game Pad ) 代表接下来的用法为Game Pad
a1 01 全局条目,代表该集合是一个应用集合
15 00 最小数据域,为0
25 01 最大数据域,为1
35 00 物理数据域,为0
45 01 物理数据域,为1
75 01 代表每个数据域的长度为1 位
95 0f 代表该数据域的数量为16个
05 09 局部条目,说明此用途为Button 按键
19 01 局部条目,说明用途的最小值为1
29 0f 说明用途的最大值为16(也就是16个按键)
81 02 主条目,代表上述的条件用作输入,即:存在16个1位的输入,来代表按键。
95 01 代表该数据域的数量为1个
81 01 Data Var Abs(1 0 0) data1代表Constant 常数
05 01 全局条目,代表该集合是一个应用集合
25 07 最大数据域,为7
46 3b 01 物理数据域,为0x013b
75 04 代表每个数据域的长度为4位
95 01 代表该数据域的数量为1个
65 14 UNIT
09 39 Hat switch
81 42 Data Variable Absolute NoWrap Nullstate
65 00 UNIT
95 01 代表该数据域的数量为1个
81 01 Data Var Abs(1 0 0) data1代表Constant 常数
26 ff 00
46 ff 00
09 30 Usage(X)
09 31 Usage(Y)
09 32 Usage(Z)
09 35 Usage(Rz)
75 08 代表每个数据域的长度为8位
95 04 代表该数据域的数量为4个
81 02 Data Var Abs(0 1 0)
05 02 USAGE_PAGE Simulation Controls
15 00 最小数据域,为0
26 ff 00 最大数据域
09 c5
09 c4
95 02
75 08
81 02
06 00 ff
26 ff 03
46 ff 03
09 20
09 21
09 22
09 23
09 24
09 25
75 10
95 06
81 02
05 08
09 43
15 00
26 ff 00
35 00
46 ff 00
75 08
95 01
91 82
09 44
91 82
09 45
91 82
09 46
91 82
c0
上键:
0000 0080 8080 8000
0000 0000 0000 0000
0000 0000 00
下键:
0000 0480 8080 8000
0000 0000 0000 0000
0000 0000 00
右键:
0000 0280 8080 8000
0000 0000 0000 0000
0000 0000 00
左键:
0000 0680 8080 8000
0000 0000 0000 0000
0000 0000 00
总结上面数据:
0000 xx80 8080 8000 xx默认为0f
0000 0000 0000 0000
0000 0000 00
Y键:
1000 0f80 8080 8000
0000 ff00 0000 0000
0000 0000 00
A键:
0100 0f80 8080 8000
0000 0000 ff00 0000
0000 0000 00
B键:
0200 0f80 8080 8000
00ff 0000 0000 0000
0000 0000 00
X键:
0800 0f80 8080 8000
0000 00ff 0000 0000
0000 0000 00
总结上面数据:
xx00 0f80 8080 8000 xx默认为00
00aa bbcc dd00 0000 aa bb cc dd 默认为00 按下为ff
0000 0000 00
LT键:
无反应?
LB键:
4000 0f80 8080 8000
0000 0000 0000 0000
0000 0000 00
RB键:
8000 0f80 8080 8000
0000 0000 0000 0000
0000 0000 00
RT键:
0000 0f80 8080 8000
xx00 0000 0000 0000
0000 0000 00
0002 0f80 8080 8000
xx00 0000 0000 0000
0000 0000 00
0000 0f80 8080 8000
xx00 0000 0000 0000 xx为RT键按下的量,最大是ff,不按下是00
0000 0000 00
菜单键:
0010 0f80 8080 8000
0000 0000 0000 0000
0000 0000 00
返回键:
0004 0f80 8080 8000
0000 0000 0000 0000
0000 0000 00
中间键:
0008 0f80 8080 8000
0000 0000 0000 0000
0000 0000 00
左摇杆
0000 0fxx yy80 8000 xx代表左右摇 yy代表上下摇
0000 0000 0000 0000
0000 0000 00
右摇杆
0000 0f80 80xx yy00 xx代表左右摇 yy代表上下摇
0000 0000 0000 0000
0000 0000 00