USB鼠标实现——设备限定描述符(五)

news/2025/1/24 16:22:32/

文章目录

  • 设备限定描述符
    • 仓库地址
    • USB 鼠标阅读顺序
    • 设备限定描述符介绍
      • 设备限定描述符结构体定义
    • 获取设备限定描述符的请求
      • 标准设备请求
      • USB 控制端点收到的数据
      • 设备限定描述符返回
    • 附 STM32 枚举日志

设备限定描述符

仓库地址

仓库地址

USB 鼠标阅读顺序

  • 枚举过程
  • USB鼠标实现——设备描述符(一)
  • USB鼠标实现——设置地址(二)
  • USB鼠标实现——配置描述符集合(三)
  • USB鼠标实现——字符串描述符(四)
  • USB鼠标实现——设备限定描述符(五)
  • USB鼠标实现——设置配置和获取配置(六)
  • USB鼠标实现——报告描述符(七)
  • USB鼠标实现——HID 报告的返回(八)

设备限定描述符介绍

在这里插入图片描述

设备限定描述符(Device Qualifier Descriptor)说明了能进行高速操作的设备在其他速度时产生的变化信息。例如,如果设备当前在全速下操作,设备限定描述符返回它如何在高速运行的信息。

如果设备既支持全速状态又支持高速状态,那么就必须含有设备限定描述符(Device Qualifier Descriptor)。设备限定描述符(Device Qualifier Descriptor)中含有当前没有使用的速度下这些字段的取值。

设备限定描述符(Device Qualifier Descriptor)不包含标准设备描述符中的厂商、产品、设备、制造厂商、产品和序列号场,因为在所有支持的速度下设备的这些信息都是常数。这个描述符的版本号至少是2.0(0200H)。

如果只能进行全速(full-speed)操作的设备(设备描述符的版本号等于0200H)接收到请求设备限定符的Get Descriptor请求,它必须用请求错误响应,回复STALL来响应

主机端只能在成功取得设备限定描述符(Device Qualifier Descriptor)之后,才能请求其他速度配置(other_speed_configuration)描述符。

  • bLength:0x0a
    • 设备限定描述符的长度。
  • bDescriptorType:0x06
    • 设备限定描述符类型,为DEVICE_QUALIFIER (0x06)。
  • bcdUSB:版本号
    • 是设备所符合的USB规范的版本号,该值采用BCD(用二进制编码的十进制数)格式。USB 2.0是0x0200;USB 2.1是0x0210。
  • bDeviceClass类码
    • 这个字段为那些在设备层次定义功能的设备规定了它们所属的类。
  • bDeviceSubClass子类码
    • 这个字段规定一个类的子类
  • bDeviceProtocol协议码
    • 这个字段为所选的类和子类规定一个协议。
  • bMaxPacketSize0
    • 为其他速度(Other-speed)的端点0最大包大小。
  • bNumConfigurations
    • 为其他速度(Other-speed)配置的数量。

设备限定描述符结构体定义

typedef struct __attribute__ ((packed))
{uint8_t  bLength            ; ///< Size of descriptoruint8_t  bDescriptorType    ; ///< Device Qualifier Typeuint16_t bcdUSB             ; ///< USB specification version number (e.g., 0200H for V2.00)uint8_t  bDeviceClass       ; ///< Class Codeuint8_t  bDeviceSubClass    ; ///< SubClass Codeuint8_t  bDeviceProtocol    ; ///< Protocol Codeuint8_t  bMaxPacketSize0    ; ///< Maximum packet size for other speeduint8_t  bNumConfigurations ; ///< Number of Other-speed Configurationsuint8_t  bReserved          ; ///< Reserved for future use, must be zero
}usb_desc_device_qualifier_t;

获取设备限定描述符的请求

标准设备请求

typedef struct __attribute__ ((packed)){union {struct __attribute__ ((packed)) {uint8_t recipient :  5; ///< Recipient type usb_request_recipient_t.uint8_t type      :  2; ///< Request type usb_request_type_t.uint8_t direction :  1; ///< Direction type. usb_dir_t} bmRequestType_bit;uint8_t bmRequestType;};uint8_t  bRequest;uint16_t wValue;uint16_t wIndex;uint16_t wLength;
} usb_control_request_t;

USB 控制端点收到的数据

0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0
  • bmRequestType:0x80
    • 数据传输方向为 1,device-to-host
    • 标准请求
    • 请求的接收者为设备
  • bRequest:0x06
    • GET_DESCRIPTOR 获取描述符请求
  • wValue:0x0006(LSB)
    • 低位:0x06 设备限定描述符
    • 高位:0x00 索引号
  • wIndex:0x0000(LSB)
    • 低位:0x00
    • 高位:0x00
  • wLength:0x0a
    • 低位:0x0a 请求返回的字节数为 0x0a,设备限定描述符的长度为 0x0a
    • 高位:0x00

设备限定描述符返回

由于当前只能进行全速(full-speed)操作(设备描述符的版本号等于0200H),设备接收到请求设备限定符的 Get Descriptor 请求,它必须用请求错误响应,回复 STALL 来响应。

USB 传输日志片段如下:

output ep int 
h->d: 0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0 
send xfer complete event
get device qualifier
stall ep0

如果需要返回设备限定描述符,设备限定描述符的实现如下(当前未使用)

usb_desc_device_qualifier_t const desc_device_qualifier =
{.bLength            = sizeof(usb_desc_device_qualifier_t),.bDescriptorType    = USB_DESC_DEVICE_QUALIFIER,.bcdUSB             = USB_BCD,.bDeviceClass       = 0x00,.bDeviceSubClass    = 0x00,.bDeviceProtocol    = 0x00,.bMaxPacketSize0    = USBD_ENDPOINT0_SIZE,.bNumConfigurations = 0x01,.bReserved          = 0x00
};

附 STM32 枚举日志

HID 鼠标枚举过程分析

suspend int
bus reset int
enum done int
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x1 0x0 0x0 0x40 0x0 
dcd xfer
input ep int 
d->h :0x12 0x1 0x0 0x2 0x0 0x0 0x0 0x40 0xfe 0xca 0x8 0x40 0x0 0x1 0x1 0x2 0x3 0x1 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
bus reset int
output ep int 
send xfer complete event
enum done int
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x0 0x5 0x5 0x0 0x0 0x0 0x0 0x0 
dcd xfer
input ep int 
edpt int send xfer complete event
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x1 0x0 0x0 0x12 0x0 
dcd xfer
input ep int 
d->h :0x12 0x1 0x0 0x2 0x0 0x0 0x0 0x40 0xfe 0xca 0x8 0x40 0x0 0x1 0x1 0x2 0x3 0x1 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
output ep int 
send xfer complete event
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x2 0x0 0x0 0xff 0x0 
dcd xfer
input ep int 
d->h :0x9 0x2 0x22 0x0 0x1 0x1 0x0 0xa0 0x32 0x9 0x4 0x0 0x0 0x1 0x3 0x1 0x2 0x0 0x9 0x21 0x11 0x1 0x0 0x1 0x22 0x4d 0x0 0x7 0x5 0x81 0x3 0x8 0x0 0xa 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x3 0x3 0x9 0x4 0xff 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0xe 0x3 0x31 0x0 0x32 0x0 0x33 0x0 0x34 0x0 0x35 0x0 0x36 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x3 0x0 0x0 0xff 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x4 0x3 0x9 0x4 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x2 0x3 0x9 0x4 0xff 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x1e 0x3 0x74 0x0 0x79 0x0 0x75 0x0 0x73 0x0 0x74 0x0 0x6c 0x0 0x69 0x0 0x20 0x0 0x44 0x0 0x65 0x0 0x76 0x0 0x69 0x0 0x63 0x0 0x65 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0 
send xfer complete event
get device qualifier
stall ep0
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x1 0x0 0x0 0x12 0x0 
dcd xfer
input ep int 
d->h :0x12 0x1 0x0 0x2 0x0 0x0 0x0 0x40 0xfe 0xca 0x8 0x40 0x0 0x1 0x1 0x2 0x3 0x1 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x2 0x0 0x0 0x9 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x9 0x2 0x22 0x0 0x1 0x1 0x0 0xa0 0x32 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x2 0x0 0x0 0x22 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x9 0x2 0x22 0x0 0x1 0x1 0x0 0xa0 0x32 0x9 0x4 0x0 0x0 0x1 0x3 0x1 0x2 0x0 0x9 0x21 0x11 0x1 0x0 0x1 0x22 0x4d 0x0 0x7 0x5 0x81 0x3 0x8 0x0 0xa 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x0 0x9 0x1 0x0 0x0 0x0 0x0 0x0 
send xfer complete event
edpt open
dcd xfer
input ep int 
edpt int send xfer complete event
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x21 0xa 0x0 0x0 0x0 0x0 0x0 0x0 
dcd xfer
input ep int 
edpt int send xfer complete event
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x81 0x6 0x0 0x22 0x0 0x0 0x8d 0x0 
dcd xfer
input ep int 
d->h :0x5 0x1 0x9 0x2 0xa1 0x1 0x9 0x1 0xa1 0x0 0x5 0x9 0x19 0x1 0x29 0x5 0x15 0x0 0x25 0x1 0x95 0x5 0x75 0x1 0x81 0x2 0x95 0x1 0x75 0x3 0x81 0x1 0x5 0x1 0x9 0x30 0x9 0x31 0x15 0x81 0x25 0x7f 0x95 0x2 0x75 0x8 0x81 0x6 0x9 0x38 0x15 0x81 0x25 0x7f 0x95 0x1 0x75 0x8 0x81 0x6 0x5 0xc 0xa 0x38 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
input ep int 
d->h :0x2 0x15 0x81 0x25 0x7f 0x95 0x1 0x75 0x8 0x81 0x6 0xc0 0xc0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
output ep int 
send xfer complete event
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x3 0x0 0x0 0xff 0x0 
dcd xfer
input ep int 
d->h :0x4 0x3 0x9 0x4 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x0 0x3 0x0 0x0 0xff 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x4 0x3 0x9 0x4 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x1 0x3 0x9 0x4 0xff 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x10 0x3 0x74 0x0 0x79 0x0 0x75 0x0 0x73 0x0 0x74 0x0 0x6c 0x0 0x69 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x1 0x3 0x9 0x4 0xff 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x10 0x3 0x74 0x0 0x79 0x0 0x75 0x0 0x73 0x0 0x74 0x0 0x6c 0x0 0x69 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x2 0x3 0x9 0x4 0xff 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x1e 0x3 0x74 0x0 0x79 0x0 0x75 0x0 0x73 0x0 0x74 0x0 0x6c 0x0 0x69 0x0 0x20 0x0 0x44 0x0 0x65 0x0 0x76 0x0 0x69 0x0 0x63 0x0 0x65 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
setup packed recvd
setup packed done
output ep int 
h->d: 0x80 0x6 0x2 0x3 0x9 0x4 0xff 0x0 
send xfer complete event
dcd xfer
input ep int 
d->h :0x1e 0x3 0x74 0x0 0x79 0x0 0x75 0x0 0x73 0x0 0x74 0x0 0x6c 0x0 0x69 0x0 0x20 0x0 0x44 0x0 0x65 0x0 0x76 0x0 0x69 0x0 0x63 0x0 0x65 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
rxflvl int
output ep int 
send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event
dcd xfer
0x0 0x5 0x5 0x0 0x0 
input ep int 
d->h :0x0 0x5 0x5 0x0 0x0 
turn off txfe
input ep int 
edpt int send xfer complete event

http://www.ppmy.cn/news/36840.html

相关文章

Linux及常用命令

日升时奋斗&#xff0c;日落时自省 目录 1、Linux概述 2、LInux环境搭建 3、终端软件XShell 7 4、Linux常用命令 4.1、操作命令 4.1.1、ls查看文件或者目录 4.1.2、pwd显示当前路径 4.1.3、cd进入目录 4.1.4、touch创建文件 4.1.5、cat查看目录 4.1.6、mkdir创建目录…

基于springboot实现家政服务管理平台【源码+论文】

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 摘要 随着家政服务行…

java八股文--数据库

数据库1.索引的基本原理2.聚簇和非聚簇索引的区别&#xff08;1&#xff09;聚簇索引优势&#xff08;2&#xff09;聚簇索引的劣势4.索引的设计原则5.事务的基本特性和隔离级别6.mysql主从同步原理7.简述MyISAM和InnoDB的区别8.简述mysql中索引类型及对数据库性能的影响9.Expl…

DETR训练自己的数据集

目录重要的参考链接第一步&#xff1a;更改权重文件第二步&#xff1a;将数据集整理为coco数据集的格式第三步&#xff1a;更改detr.py第四步&#xff1a;在终端设置训练参数进行训练第五步&#xff1a;检测效果&#xff0c;但是没有没有打印出来那些map指标重要的参考链接 视…

Java对象与类

目录专栏导读一、面向对象程序设计1、类2、封装3、对象的三大特征4、类之间的关系5、隐式参数与显示参数6、静态字段与静态方法7、静态方法二、对象构造1、重载2、默认字段初始化3、对象析构三、包四、注释1、类注释2、方法注释3、字段注释五、抽象类专栏导读 &#x1f3c6;作者…

从零开始学Python第09课:常用数据结构之列表-2

列表的方法 列表类型的变量拥有很多方法可以帮助我们操作一个列表&#xff0c;假设我们有名为foos的列表&#xff0c;列表有名为bar的方法&#xff0c;那么使用列表方法的语法是&#xff1a;foos.bar()&#xff0c;这是一种通过对象引用调用对象方法的语法。后面我们讲面向对象…

Python __call__()方法

本节再介绍 Python 类中一个非常特殊的实例方法&#xff0c;即 __call__()。该方法的功能类似于在类中重载 () 运算符&#xff0c;使得类实例对象可以像调用普通函数那样&#xff0c;以“对象名()”的形式使用。 举个例子&#xff1a; class CLanguage:# 定义__call__方法def …

循环神经网络

循环神经网络(Recurrent Neural Network&#xff0c;RNN)与卷积神经网络一样,都是深度学习中的重要部分。循环神经网络可以看作一类具有短期记忆能力的神经网络。在循环神经网络中&#xff0c;神经元不但可以接收其他神经元的信息&#xff0c;也可以接收自身的信息&#xff0c;…