USB 设备功能按接口来分类,一个接口代表一种功能,接口下的端点用于实现该接口下的数据通讯功能。
Report 描述符用于描述 HID 设备的功能和设备上报的数据信息格式,Physical 描述符集(可选),它携带如人体的哪个部位操作此设备的信息。
HID 描述符中定义了Report 描述符的个数和长度,Report描述符的获取通过向接口发送标准请求实现(81 06 00 22 xx xx xx xx)。
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; //可能的配置数量
}
通过USB2.0 Monitor 枚举过程中获取鼠标 描述符:
一个鼠标,只有一个端点
===>> Device Desc <<===
bLength: 0x12 //设备描述符的字节数大小,为0x12
bDescriptorType: 0x01 //描述符类型编号,为0x01
bcdUSB: 0x02 00 // USB 版本号
bDeviceClass: 0x00 // 这个字节为0,则设备信息在interface
bDeviceSubClass: 0x00
bDeviceProtocol: 0x00
bMaxPacketSize0: 0x08 // 端点0 的最大包长
idVendor: 0x41 3C // 厂商编号
idProduct: 0x30 1A // 产品编号
bcdDevice: 0x01 00 // 设备出厂编号
iManufacturer: 0x01 // 描述厂商字符串的索引
iProduct 0x02 // 描述产品字符串的索引
iSerialNumber 0x00 // 描述设备序列号字符串的索引
bNumConfiguration 0x01 // 可能的配置数量
===>Configuration Descriptor<===
bLength: 0x09
bDescriptorType: 0x02 // constant
wTotalLength: 0x0022 // 请求配置所返回的所有长度
bNumInterfaces: 0x01 // 此配置支持接口数
bConfigurationValue: 0x01 // Set_Configuration命令需要的参数
iConfiguration: 0x00 // 此配置字符串的索引(第 1 个配置字符串)
bmAttributes: 0xA0 -> 1010_0000 Bus Powered + 远程唤醒
MaxPower: 0x32 // 设备从总线提取的最大电流: 0x32*2 mA = 100 mA
===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04 // Interface Type
bInterfaceNumber: 0x00 // 接口编号
bAlternateSetting: 0x00 // 备用的接口描述符编号
bNumEndpoints: 0x01 // 该接口使用端点数,不包括端点0
bInterfaceClass: 0x03 // HID 设备
bInterfaceSubClass: 0x01 // Boot Interface SubClass=1表示USB设备支持 BOOT
// 意思是BIOS启动时就能识别并使用你的设别,且只有标准鼠标或键盘类设备才能成为Boot device,
// 为0则只有在操作系统启动后才能识别并使用你的HID设备. https://www.cnblogs.com/AlwaysOnLines/p/5085211.html
bInterfaceProtocol: 0x02 // 遵循的协议(前提是BOOT Interface) 1->Keyboard 2->Mouse
iInterface: 0x00 // 描述该接口的字符串描述符的索引值
===>HID class Descriptor<===
bLength: 0x09 // HID描述符长度
bDescriptorType: 0x21 // 描述符类型 constant
bcdHID: 0x01 11 // HID 版本号(BCD码)1.1
bCountryCode: 0x00 // 国家/地区代码
bNumDescriptor: 0x01 // 支持的其它类型描述符数量
// 由于HID设备至少需要包括一个报告描述符,故其值至小为0x01。
bDescriptorType: 0x22 // 类别描述符的类型,报表描述符
b/wDescriptorLength: 0x00 2E // 可选字段,用于表示HID描述符附属的类别描述符类型及长度。
// 报告描述符的总长度 ??????????
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x81 -> Bit7,Direction: IN ; Bit3-0, EndpointID: 1
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0004 = 4 max bytes
bInterval: 0x0A // 主机查询端点的时间间隔
另一个鼠标,两个端点的情况
===>> Device Desc <<===
bLength: 0x12 //设备描述符的字节数大小,为0x12
bDescriptorType: 0x01 //描述符类型编号,为0x01
bcdUSB: 0x01 10 // USB 版本号
bDeviceClass: 0x00 // 这个字节为0,则设备信息在interface
bDeviceSubClass: 0x00
bDeviceProtocol: 0x00
bMaxPacketSize0: 0x08 // 端点0 的最大包长
idVendor: 0x30 FA // 厂商编号
idProduct: 0x17 01 // 产品编号
bcdDevice: 0x01 00 // 设备出厂编号
iManufacturer: 0x02 // 描述厂商字符串的索引
iProduct 0x01 // 描述产品字符串的索引
iSerialNumber 0x00 // 描述设备序列号字符串的索引
bNumConfiguration 0x01 // 可能的配置数量
===>Configuration Descriptor<===
bLength: 0x09
bDescriptorType: 0x02 // constant
wTotalLength: 0x003B // 请求配置所返回的所有长度
bNumInterfaces: 0x02 // 此配置支持接口数
bConfigurationValue: 0x01 // Set_Configuration命令需要的参数
iConfiguration: 0x00 // 此配置字符串的索引(第 1 个配置字符串)
bmAttributes: 0xA0 -> 1010_0000 Bus Powered + 远程唤醒
MaxPower: 0x32 // 设备从总线提取的最大电流: 0x32*2 mA = 100 mA
===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04 // Interface Type
bInterfaceNumber: 0x00 // 接口编号
bAlternateSetting: 0x00 // 备用的接口描述符编号
bNumEndpoints: 0x01 // 该接口使用端点数,不包括端点0
bInterfaceClass: 0x03 // HID 设备
bInterfaceSubClass: 0x01 // Boot Interface // SubClass=1表示USB设备支持 BOOT
bInterfaceProtocol: 0x02 // 遵循的协议(前提是BOOT Interface) 1->Keyboard 2->Mouse
iInterface: 0x00 // 描述该接口的字符串描述符的索引值
===>HID class Descriptor<===
bLength: 0x09 // HID描述符长度
bDescriptorType: 0x21 // 描述符类型 constant
bcdHID: 0x01 10 // HID 版本号(BCD码)1.1
bCountryCode: 0x00 // 国家/地区代码
bNumDescriptor: 0x01 // 支持的其它类型描述符数量
// 由于HID设备至少需要包括一个报告描述符,故其值至小为0x01。
bDescriptorType: 0x22 // 类别描述符的类型,报表描述符
b/wDescriptorLength: 0x00 42 // 可选字段,用于表示HID描述符附属的类别描述符类型及长度。
// 报告描述符的总长度 ??????????
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0008 = 8 max bytes
bInterval: 0x0A // 主机查询端点的时间间隔
===>Interface Descriptor<===
bLength: 0x09
bDescriptorType: 0x04 // Interface Type
bInterfaceNumber: 0x01 // 接口编号
bAlternateSetting: 0x00 // 备用的接口描述符编号
bNumEndpoints: 0x01 // 该接口使用端点数,不包括端点0
bInterfaceClass: 0x03 // HID 设备
bInterfaceSubClass: 0x00 // No Subclass
bInterfaceProtocol: 0x01 // 遵循的协议 1->Keyboard 2->Mouse
iInterface: 0x00 // 描述该接口的字符串描述符的索引值
===>HID class Descriptor<===
bLength: 0x09 // HID描述符长度
bDescriptorType: 0x21 // 描述符类型 constant
bcdHID: 0x01 10 // HID 版本号(BCD码)1.1
bCountryCode: 0x00 // 国家/地区代码
bNumDescriptor: 0x01 // 支持的其它类型描述符数量
// 由于HID设备至少需要包括一个报告描述符,故其值至小为0x01。
bDescriptorType: 0x22 // 类别描述符的类型:0x22->报表描述符
b/wDescriptorLength: 0x00 8C // 可选字段,用于表示HID描述符附属的类别描述符类型及长度。
// 报告描述符的总长度 ??????????
===>Endpoint Descriptor<===
bLength: 0x07
bDescriptorType: 0x05
bEndpointAddress: 0x82 -> Direction: IN - EndpointID: 2
bmAttributes: 0x03 -> Interrupt Transfer Type
wMaxPacketSize: 0x0008 = 8 max bytes
bInterval: 0x0A // 主机查询端点的时间间隔