USB学习笔记
一、USB基础内容
USB分类
没写
二、标准请求 USB 标准请求 - USB中文网
- USB定义了8个字节的标准请求,通过这些请求,可以对设备的状态进行更改或对设备进行枚举。
- USB的标准请求的数据传输方式都是控制传输方式,所以使用的端点是设备的默认端点0。
- USB这8个字节的的控制请求不包括传输过程中的数据,但包括了控制请求的数据长度。当数据长度为不为0时,设备或主机向对方传输相应长的数据。这些数据有可能是设备返回给主机的回应数据,也可能是主机发给设备的控制参数。
- USB标准请求的个字节分为5个部分,其变量分别定义为: 1字节的bmRequestType,1 字节的bReqest,2字节的wValue,2字节的wIndex和2字节的wLength.
例如获取设备描述符的标准请求:
CTL 80 06 00 01 00 00 12 00 GET DESCRIPTOR 08:56:12.278
其中80是bmRequestType,06是bRequest,00 02是wValue,00 00是请求索引参数,09 00是期望GET数据长度
80意味着该请求是标准请求,接收方是设备,数据传输方向是设备到主机;
06意味着是GET_DESCRIPTOR
00 01:是由描述符类型(高字节)和描述符索引(低字节)组成
00 00:wIndex在GET_DESCRIPTOR请求里就是00 00
12 00:数据长度-18个
- 获取配置描述符的标准请求:80 06 00 02 00 00 09 00
- 获取字符串描述符的标准请求:80 06 02 03 09 04 6A 00
- 设置设备配置选项的标准请求:00 09 01 00 00 00 00 00
- 设置接口的标准请求:21 0a 00 00 00 00 00 00
- 获取报告描述符标准请求:81 06 00 22 00 00 6E 00 (wValue[8:15] Desc Type: (HID Report))HID设备标准请求GetDescriptor之获取报告描述符 - USB中文网
/*
* USB 控制传输-请求类型 联合体 (对应USB规范9.3节)
* 用于描述USB请求的特性,使用位域和联合体实现单字节的多模式访问
*/
typedef union _BM_REQUEST_TYPE {
struct _BM { // 位域结构体 (总长度8bit)
UCHAR Recipient:2; // 请求接收方 (0000=设备, 0001=接口, 0010=端点, 0011=其他)
UCHAR Reserved:3; // 保留位(必须设为0)
UCHAR Type:2; // 请求类型 (0000=标准, 0001=类, 0010=厂商, 0011=保留)
UCHAR Dir:1; // 数据传输方向 (0=主机到设备,1=设备到主机)
#ifdef __cplusplus // C++兼容性处理:结构体名称作用域不同
} s;
#else
};
#endif
UCHAR B; // 完整的字节值(可通过此字段直接读写整个字节)
} BM_REQUEST_TYPE, *PBM_REQUEST_TYPE;
/*
* USB 默认管道设置包结构 (USB规范第9章定义的控制传输数据结构)
* 用于构建USB控制传输的Setup阶段数据包(8字节固定长度)
*/
typedef struct _USB_DEFAULT_PIPE_SETUP_PACKET {
BM_REQUEST_TYPE bmRequestType; // 请求特性(包含方向/类型/接收方)
UCHAR bRequest; // 具体请求代码(如GET_DESCRIPTOR=0x06)
union _wValue { // 请求参数(根据请求不同含义不同)
struct { // 分解为两个字节的布局
UCHAR LowByte; // 低位字节(LSB)
UCHAR HiByte; // 高位字节(MSB)
};
USHORT W; // 完整的16位值(可直接存取)
} wValue;
union _wIndex { // 请求索引参数(通常用于指定接口/端点号)
struct {
UCHAR LowByte; // 低位字节(如接口号)
UCHAR HiByte; // 高位字节(通常为0)
};
USHORT W; // 完整的16位值
} wIndex;
USHORT wLength; // 请求期望传输的数据长度(DATA阶段)
} USB_DEFAULT_PIPE_SETUP_PACKET, *PUSB_DEFAULT_PIPE_SETUP_PACKET;
bmRequestType(1) | bRequest(1) | wValue(2) | wIndex(2) | wLength(2) | 数据过程 |
---|---|---|---|---|---|
0x00 | CLEAR_FEATURE(1) | 特性选择 | 0 | 0 | 没有数据 |
0x01 | CLEAR_FEATURE(1) | 特性选择 | 接口号 | 0 | 没有数据 |
0x02 | CLEAR_FEATURE(1) | 特性选择 | 端点号 | 0 | 没有数据 |
0x80 | GET_CONFIGURATION(8) | 0 | 0 | 1 | 配置制 |
0x80 | GET_DESCRIPTOR(6) | 描述符类型(高字节)和描述符索引(低字节) | 0或语言ID(字符串描述符) | 描述符的长度 | 描述符 |
0x81 | GET_INTERFACE(0x0a) | 0 | 接口号 | 1 | 备用(转换)接口 |
0x80 | GET_STATUS(0) | 0 | 0 | 2 | 设备状态 |
0x81 | GET_STATUS(0) | 0 | 接口号 | 2 | 接口状态 |
0x82 | GET_STATUS(0) | 0 | 端点号 | 2 | 端点状态 |
0x00 | SET_ADDRESS(5) | 设备地址 | 0 | 0 | 没有数据 |
0x00 | SET_CONFIGURATION(9) | 配置值 | 0 | 0 | 没有数据 |
0x00 | SET_DESCRIPTOR(7) | 描述符类型(高字节)和描述符索引(低字节) | 0或语言ID(字符串描述符) | 描述符的长度 | 描述符 |
0x00 | SET_FEATURE(3) | 特性选择 | 0 | 0 | 没有数据 |
0x01 | SET_FEATURE(3) | 特性选择 | 接口号 | 0 | 没有数据 |
0x02 | SET_FEATURE(3) | 特性选择 | 端点号 | 0 | 没有数据 |
0x01 | SET_INTERFACE(0x0b) | 备用接口号(转换接口号) | 接口号 | 0 | 没有数据 |
0x82 | SYNCH_FRAME(0x0c) | 0 | 端点号 | 2 | 帧号 |
三、设备描述符
- USB设备描述符是USB设备在进行插拔和初始化过程中,最先被主机读取的一部分信息,它包含了设备的一些基本属性信息,如USB规范版本、设备类、设备子类、设备协议、最大数据包长度等。
- USB设备描述符通常是在设备插入时被主机读取,在获取到设备描述符后,主机可以自动加载相应的驱动程序,完成设备的初始化和配置。
- 设备描述符是USB设备的第一个描述符,每个USB设备都得具有设备描述符,且只能拥有一个。
产品boot设备描述符分析
IN 12 01 00 02 00 00 00 40 f7 1f 0a 0f 00 01 01 02 03 01 08:56:12.278
- 12:设备描述符的字节数大小,为0x12
- 01:描述符类型编
- 00 02:USB版本号-USB2.0
- 00 00:低位:设备类别:由接口描述符定义,见于复合设备(如带存储和HID功能的设备)。
高位:设备子类:无特定子类。 - 00 40:低位:设备协议:无特定协议。
高位:端点0最大包大小:64字节。 - F7 1F: VID:0X1FF7
- 0A 0F: PID:0X0F0A
- 00 01: 厂商出厂设备编号,PVN:0X0100
- 01:厂商字符串索引:指向字符串描述符1,用于获取厂商名称
- 02:产品字符串索引:指向字符串描述符2,用于获取产品名称(“USB Flash Drive”)。
- 03:序列号字符串索引:指向字符串描述符3,用于唯一标识设备。
- 01:配置描述符数量:仅1个配置。
产品app设备描述符分析
12 01 00 02 00 00 00 40 f7 1f 32 0f 00 48 01 02 03 01
struct _DEVICE_DESCRIPTOR_STRUCT
{
BYTE bLength; //设备描述符的字节数大小,为0x12
BYTE bDescriptorType; //描述符类型编号,为0x01
WORD bcdUSB; //USB版本号
BYTE bDeviceClass; //USB分配的设备类代码,0x01~0xfe为标准设备类,0xff为厂商自定义类型
//0x00不是在设备描述符中定义的,如HID
BYTE bDeviceSubClass; //usb分配的子类代码,同上,值由USB规定和分配的
BYTE bDeviceProtocol; //USB分配的设备协议代码,同上
BYTE bMaxPacketSize0; //端点0的最大包的大小
WORD idVendor; //厂商编号
WORD idProduct; //产品编号
WORD bcdDevice; //设备出厂编号
BYTE iManufacturer; //描述厂商字符串的索引
BYTE iProduct; //描述产品字符串的索引
BYTE iSerialNumber; //描述设备序列号字符串的索引
BYTE bNumConfiguration; //可能的配置数量
}
四、配置描述符
- 读取配置描述符时,它会返回整个配置层次结构,其中包括所有相关的接口和端点描述符。wTotalLength字段反映配置描述符层次结构中的字节数。
- 配置描述符在USB设备的枚举过程中,需要获取两次:
- 第一次只获取配置描述符的基本长度9字节,获取后从wTotalLength字节中解析出配置描述符的总长度,然后再次获取全部的描述符。
- 配置描述数据中不仅包括配置描述符本身,也包括其下的接口描述符和端点描述符。
标准请求:80 06 00 02 00 00 09 00,从设备获取描述符,描述符类型由第四位字节02确定,为配置描述符,第一次获取数据长度为9,获取到配置描述符:09 02 29 00 01 01 00 a0 32后,根据数据中的第三位字节29确定描述符总长度为0X29,第二次发送获取描述符标准请求:80 06 00 02 00 00 29 00,与第一次不同的只有数据长度字节变为了29,获取到整个配置描述符。
boot配置描述符
`IN 09 02 29 00 01 01 00 a0 32 09 04 00 00 02 03 00 00 00 09 21 00 02 00 01 22 2e 00 07 05 81 03 40 00 01 07 05 01 03 40 00 01`
#### **1、配置描述符(Configuration Descriptor)**
09 02 29 00 01 01 00 a0 32
`09`:描述符长度(9 字节)
`02`:描述符类型(配置描述符)
`29 00`:总长度(41 字节)
`01`:配置数量
`01`:配置值
`00`:配置字符串索引
`a0`:属性(总线供电,远程唤醒)
`32`:最大电流(100 mA)
#### **2、接口描述符(Interface Descriptor)**
09 04 00 00 02 03 00 00 00
`09`:描述符长度(9 字节)
`04`:描述符类型(接口描述符)
`00`:接口编号
`00`:备用设置
`02`:端点数量
`03`:接口类(HID)
`00`:接口子类
`00`:接口协议
`00`:接口字符串索引
#### **3、HID 描述符(HID Descriptor)**
09 21 00 02 00 01 22 2e 00
`09`:描述符长度(9 字节)
`21`:描述符类型(HID 描述符)
`00 02`:HID 版本(2.00)
`00`:国家代码
`01`:类描述符数量
`22`:描述符类型(报告描述符)
`2e 00`:描述符长度(46 字节)
#### **4、端点描述符(Endpoint Descriptor)**
07 05 81 03 40 00 01
`07`:描述符长度(7 字节)
`05`:描述符类型(端点描述符)
`81`:端点地址(IN 端点 1)
`03`:属性(中断传输)
`40 00`:最大包大小(64 字节)
`01`:轮询间隔(1 毫秒)
#### **5、端点描述符(Endpoint Descriptor)**
07 05 01 03 40 00 01
`07`:描述符长度(7 字节)
`05`:描述符类型(端点描述符)
`01`:端点地址(OUT 端点 1)
`03`:属性(中断传输)
`40 00`:最大包大小(64 字节)
`01`:轮询间隔(1 毫秒)
总结:
`09 02 29 00 01 01 00 a0 32` 是配置描述符。
`09 04 00 00 02 03 00 00 00` 是接口描述符。
`09 21 00 02 00 01 22 2e 00` 是 HID 描述符。
`07 05 81 03 40 00 01` 是 IN 端点描述符。
`07 05 01 03 40 00 01` 是 OUT 端点描述符
### 产品的配置描述符
`IN 09 02 69 00 03 01 00 a0 32 09 04 00 00 02 03 00 00 00 09 21 00 02 00 01 22 c6 02 07 05 81 03 40 00 01 07 05 01 03 40 00 01 09 04 01 00 02 03 00 00 00 09 21 00 02 00 01 22 5e 00 07 05 82 03 08 00 01 07 05 02 03 08 00 01 09 04 02 00 02 03 00 00 00 09 21 00 02 00 01 22 04 02 07 05 83 03 3e 00 01 07 05 03 03 3e 00 01`
Configuration Descriptor (9字节)
|- Interface 0 Descriptor (9字节)
| |- HID Descriptor (9字节)
| |- Endpoint 1 IN (7字节)
| |- Endpoint 1 OUT (7字节)
|- Interface 1 Descriptor (9字节)
| |- HID Descriptor (9字节)
| |- Endpoint 2 IN (7字节)
| |- Endpoint 2 OUT (7字节)
|- Interface 2 Descriptor (9字节)
| |- HID Descriptor (9字节)
| |- Endpoint 3 IN (7字节)
| |- Endpoint 3 OUT (7字节)
配置描述符(Configuration Descriptor)
`09 02 69 00 03 01 00 a0 32`
- `09`:描述符长度(9 字节)
- `02`:描述符类型(配置描述符)
- `69 00`:总长度(105 字节)
- `03`:配置三个接口
- `01`:配置值
- `00`:配置字符串索引
- `a0`:属性(总线供电,远程唤醒)
- `32`:最大电流(100 mA)
1. 接口0(Interface 0)
09 04 00 00 02 03 00 00 00 // 接口描述符(Interface 0)
09 21 00 02 00 01 22 C6 02 // HID描述符(HID 1.0,报告描述符长度710字节)
07 05 81 03 40 00 01 // 端点1 IN(中断传输,64字节包大小,轮询间隔1ms)
07 05 01 03 40 00 01 // 端点1 OUT(中断传输,64字节包大小,轮询间隔1ms)
2. 接口1(Interface 1)
09 04 01 00 02 03 00 00 00 // 接口描述符(Interface 1)
09 21 00 02 00 01 22 5E 00 // HID描述符(HID 1.0,报告描述符长度94字节)
07 05 82 03 08 00 01 // 端点2 IN(中断传输,8字节包大小,轮询间隔1ms)
07 05 02 03 08 00 01 // 端点2 OUT(中断传输,8字节包大小,轮询间隔1ms)
3. 接口2(Interface 2)
09 04 02 00 02 03 00 00 00 // 接口描述符(Interface 2)
09 21 00 02 00 01 22 04 02 // HID描述符(HID 1.0,报告描述符长度516字节)
07 05 83 03 3E 00 01 // 端点3 IN(中断传输,62字节包大小,轮询间隔1ms)
07 05 03 03 3E 00 01 // 端点3 OUT(中断传输,62字节包大小,轮询间隔1ms)
五、字符串描述符
根据设备描述符的15、16、17字节的值,设备有描述厂商字符串的索引,描述产品字符串的索引,描述设备序列号字符串的索引,在枚举中,首先通过标准请求 80 06 02 03 09 04 04 00
获取设备的产品字符串描述符
APP的产品字符串描述符
6a 03 43 00 44 00 2d 00 45 00 42 00 37 00 35 00 42 00 32 00 2d 00 43 00 2d 00 41 00 31 00 2d 00 46 00 2d 00 32 00 30 00 50 00 2c 00 37 00 35 00 20 00 32 00 30 00 20 00 34 00 38 00 30 0030 00 2d 00 44 00 38 00 34 00 35 00 2c 00 32 00 30 00 32 00 32 00 31 00 32 00 31 00 33 00 2d 00 32 00 31 00 30 00 30 00 35 00 31 00
APP的厂商字符串描述符
24 03 54 00
APP的设备序列号字符串描述符
16 03 44 00
设备的完整字符串描述符是在用户访问USB设备信息时实时从设备上获取的,例如:查看设备管理器里的设备的属性时,主机会向设备发送三个获取字符串描述符的控制传输指令
六、HID报告描述符 HID 报表描述符/报告描述符 - USB中文网
报表描述符用于描述USB HID与主机之间传输的数据的用途和数据格式的。通过报表描述符,USB主机可以区分出报告里的数据表的含义。报表描述符和设备描述符、配置描述符和字符串描述一样,都有一个固定的描述符类型ID,并且是通过GET_DESCRIPTOR来获取的,只不过该请求发向的是USB设备的接口。
一个报表描述符可以多个数据格式,就如同一个我们可以将要传输的多种数据结构放在一个大的结构体中一样,不同的报表内容区分可以使用报告ID来识别。报告ID在报表描述符的最前端,即第一个字节。如果报描述符只包含一个报告,可以不设计报告ID.报告ID之后一般是实际的报告数据。
HID报告描述符由一系列项目(Items)组成,这些项目定义了设备如何向主机报告数据以及主机如何发送数据到设备。每个项目可以属于Main、Global或Local类型。Main项目用于定义集合的开始和结束,Global项目设置全局状态(如用途页、逻辑最小值等),而Local项目定义特定字段的属性(如用途、最小值等)。
主项目(main item)
主项目用于定义数据域或者用于进行数据域的分组。
主项目其有5个,分别为Input,Output,Feature,Collection和End Collection.
Collection和End Collection项目
Collection共有四种,分别为Physical,Application,Logical和Vendoer Defined.
所有的报表类型都可以使用Collection与 End Collection项目来将相关的Main类型项目组成群组。这两个项目分别用于打开和关闭集合。所有在Collection与End Collection项目之间的Main类型项目都是 Collection的一部分。
Collection有3种类型:Application、Physical与Logical,其项目的数据项的值分别为1、0和2。厂商也可以自己定义Collection类型,数据项的值为80h~FFh保留给厂商定义。End Collection项目无数据项。
Application Collection包含有共同用途的项目或执行单一功能的项目。例如键盘的开机描述符将键盘的按键与LED指示灯数据集合成一个Application Collection。所有的报表必须在一个Application Collection内。
Physical Collection包含在一个单一几何点上的数据项目,可以将每个位置的数据集合成一个 Physical Collection。在设备报告多个传感器的位置的时候,使用Physical Collection指明不同的数据来自不同的传感器。
Logical Collection形成一个数据结构,包含由 Collection所连结的不同类型的项目。例如数据缓冲区的内容以及缓冲区内字节数目的计数。
COLLCTION(Physical) A1 00
COLLCTION(Application) A1 01
COLLCTION(Logical) A1 02
COLLCTION(Vendoer Defined.) A1 xx
Blockquote
End Collection是Collection条目的结束标志:
END_COLLECTION C0
全局项目(Global Item)
全局项目主要用来选择用途页(Usage Page),定义数据域的长度(Report Count)、数量(Report Size)、报告ID(ReportId)等。
全局项目描述对后续的所有项目有效,除非遇到有新的全局项目。
常见的全局项目有:
Usage Page(用途页)
Logical Minimum(逻辑最小值)
Logical Maxinum(逻辑最大值)
Physical Minimum(物理最小值)
Physical Maximum(物理最大值)
Report Size:数据域大小,表示每个数据域有多少位
Report Count:数据域有多少个数据域。
ReportId:报告ID
局部项目(local Item)
局部项目用于定义数据的控制特性,如该数据域的用途,用途的最大值,用途的最小值等。
局部项目只在局部有效,遇到一个主条目后,它的失效。
常见的局部数据项目有:
Usage :用途
Usage Minmum:用途的最小值
Usage Maxmum:用途的最大值。
产品HID报表描述符
05 0d 09 04 a1 01 85 32 75 08 95 01 81 03 09 54 15 00 26 80 00 81 02 09 22 a1 02 09 42 15 00 25
01 75 01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 25 7f 81 02 05 01 75
10 55 0e 65 11 15 00 35 00 09 30 26 ff 7f 46 14 4b 81 02 09 31 26 ff 7f 46 e4 2a 81 02 05 0d 09
48 26 14 4b 46 14 4b 81 02 09 49 26 e4 2a 46 e4 2a 81 02 09 30 55 00 65 00 15 00 26 ff 0f 81 02
09 3f 55 0f 65 14 15 00 27 00 00 01 00 35 00 47 a0 8c 00 00 81 02 c0 a1 02 09 42 15 00 25 01 75
01 95 01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 25 7f 81 02 05 01 75 10 55
0e 65 11 15 00 35 00 09 30 26 ff 7f 46 14 4b 81 02 09 31 26 ff 7f 46 e4 2a 81 02 05 0d 09 48 26
14 4b 46 14 4b 81 02 09 49 26 e4 2a 46 e4 2a 81 02 09 30 55 00 65 00 15 00 26 ff 0f 81 02 09 3f
55 0f 65 14 15 00 27 00 00 01 00 35 00 47 a0 8c 00 00 81 02 c0 a1 02 09 42 15 00 25 01 75 01 95
01 81 02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 25 7f 81 02 05 01 75 10 55 0e 65
11 15 00 35 00 09 30 26 ff 7f 46 14 4b 81 02 09 31 26 ff 7f 46 e4 2a 81 02 05 0d 09 48 26 14 4b
46 14 4b 81 02 09 49 26 e4 2a 46 e4 2a 81 02 09 30 55 00 65 00 15 00 26 ff 0f 81 02 09 3f 55 0f
65 14 15 00 27 00 00 01 00 35 00 47 a0 8c 00 00 81 02 c0 a1 02 09 42 15 00 25 01 75 01 95 01 81
02 09 32 81 02 09 47 81 02 95 05 81 03 09 51 75 08 95 01 25 7f 81 02 05 01 75 10 55 0e 65 11 15
00 35 00 09 30 26 ff 7f 46 14 4b 81 02 09 31 26 ff 7f 46 e4 2a 81 02 05 0d 09 48 26 14 4b 46 14
4b 81 02 09 49 26 e4 2a 46 e4 2a 81 02 09 30 55 00 65 00 15 00 26 ff 0f 81 02 09 3f 55 0f 65 14
15 00 27 00 00 01 00 35 00 47 a0 8c 00 00 81 02 c0 75 08 95 05 81 01 05 0d 85 07 09 55 15 00 26
80 00 b1 02 c0
05 01 09 02 a1 01 09 01 a1 00 85 01 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05
81 03 05 01 09 30 09 31 15 00 26 ff 7f 35 00 46 ff 7f 75 10 95 02 81 02 05 0d 09 33 15 00 26 ff
00 35 00 46 ff 00 75 08 95 01 81 02 05 01 09 38 15 81 25 7f 35 81 45 7f 95 01 81 06 c0 c0
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x85, 0x01, // Report ID (1)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (0x01)
0x29, 0x03, // Usage Maximum (0x03)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x03, // Report Count (3)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01, // Report Count (1)
0x75, 0x05, // Report Size (5)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x7F, // Logical Maximum (32767)
0x35, 0x00, // Physical Minimum (0)
0x46, 0xFF, 0x7F, // Physical Maximum (32767)
0x75, 0x10, // Report Size (16)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x0D, // Usage Page (Digitizer)
0x09, 0x33, // Usage (Touch)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x35, 0x00, // Physical Minimum (0)
0x46, 0xFF, 0x00, // Physical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x38, // Usage (Wheel)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x35, 0x81, // Physical Minimum (-127)
0x45, 0x7F, // Physical Maximum (127)
0x95, 0x01, // Report Count (1)
0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0xC0, // End Collection
疑惑
问题1:为什么两次获取的配置描述符不同,第一次有三个interface,第二次只有一个
产品是复合类设备,在设备表里有一个USB port下有三个接口(interface),每个接口下有数量不定的设备,第一次的配置描述符里有产品的配置描述符+三个接口的接口描述符,每个接口均是HID设备,所以有HID描述符,以及接口下的端点描述符;第二次获取的配置描述符是主机对产品三个接口下的接口1的枚举产生的配置描述符,只包含接口一的配置描述符。
问题2:为什么一号接口描述符里的HID描述符已经提到数据长度是0X02C6,后面获取HID报告描述符时申请的数据长度却是0X0306,这个0X0306是怎么来的
0X0306由主机产生,和主机有关,只要大于咱的HID描述符数据长度就OK了。
问题3:这个710字节的HID报告描述符有些复杂,不知道该如何去分析。
HID报告描述符表达了设备上传数据的格式,对照着数据格式和HID协议看。
问题1:配置描述符里有三个接口描述符,均是HID设备