USB 2.0 协议专栏之 USB 配置描述符(四)

news2024/9/21 13:51:00

前言:本篇博客为手把手教学的 USB 2.0 协议栈类精品博客,该专栏博客侧重针对 USB 2.0 协议进行讲解。第 4 篇重点为 USB 2.0 协议中的配置描述符 Configuration Descriptors 进行讲解,并结合 CH32V307 STM32 代码进行 Configuration Descriptors 分析。USB 协议栈是嵌入式工程研发过程中很大的坑,USB 协议栈非常冗杂且深奥,但它在工程项目中却至关重要,希望这篇博文能给读者朋友的工程项目给予些许帮助,Respect!

Universal Serial Bus 版本:

 USB Descriptor:

推荐网址

USB官网:Front Page | USB-IF

USB中文网:USB中文网 (usbzh.com)

沁恒WCH官网:首页 - 南京沁恒微电子股份有限公司 (wch.cn)

一、配置描述符

USB 描述符其实就是 C 语言里面的结构体 Structure 和数组 Array,数组包含的信息说明当前的设备具有哪些特征。USB 描述符有设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符,HID 设备有 HID 描述符、报告描述符和物理描述符。我们先学会每个描述符的细节,作者会进行非常详细的讲解,后期在回顾 USB 枚举的时候会通过抓包和波形来学习每一个描述符在总线上的作用,并且会介绍每一个描述符是在什么时候以哪种方式在总线上进行传输的,本篇博客是重点学习 USB Configuration Descriptors 的组成。

一个USB设备至少有一个或者多个配置,这一点可以从设备描述符的最后一项 bNumConfigurations 得到,但是当前只能选择其中一种配置,每一种配置都对应一个配置描述符集合,为什么说是一个集合呢,因为这个配置包括:标准配置描述符 Configuration Descriptors、接口描述符 Interface Descriptors、端点描述符 Endpoint Descriptors,如果是 HID 设备还会包括 HID 描述符,我们今天讲的是标准配置描述符,后期会讲解其他的描述符。标准配置描述符只有 9 个字节,组成如下:

二、MCU配置描述符代码

2.1 STM32代码

/* USB Configuration Descriptor */
const uint8_t CustomHID_ConfigDescriptor[CUSTOMHID_SIZ_CONFIG_DESC] =
{
/* 标准配置描述符 */
    0x09, /* bLength: Configuation Descriptor size */
    USB_CONFIGURATION_DESCRIPTOR_TYPE, 	/* bDescriptorType: Configuration */
    CUSTOMHID_SIZ_CONFIG_DESC,			/* wTotalLength low : Bytes returned */
    0x00,								/* wTotalLength high: Bytes returned */
    0x01,         /* bNumInterfaces: 1 interface */
    0x01,         /* bConfigurationValue: Configuration value */
    0x00,         /* iConfiguration: Index of string descriptor describing the configuration*/
    0xC0,         /* bmAttributes: Bus powered */
                  /*Bus powered: 7th bit, Self Powered: 6th bit, Remote wakeup: 5th bit, reserved: 4..0 bits */
    0x96,         /* MaxPower 300 mA: this current is used for detecting Vbus */
    
/* 接口描述符 */		
	/************** Descriptor of Custom HID interface ****************/
    /* 09 */
    0x09,         						/* bLength: Interface Descriptor size */
    USB_INTERFACE_DESCRIPTOR_TYPE,		/* bDescriptorType: Interface descriptor type */
    0x00,         /* bInterfaceNumber: Number of Interface */
    0x00,         /* bAlternateSetting: Alternate setting */
    0x02,         /* bNumEndpoints 此接口有两个端点 */
    0x03,         /* bInterfaceClass: HID */
    0x00,         /* bInterfaceSubClass : 1=BOOT, 0=no boot */
    0x00,         /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
    0,            /* iInterface: Index of string descriptor */
    
/* HID描述符(后续讲解)*/	
	/******************** Descriptor of Custom HID HID ********************/
    /* 18 */
    0x09,         /* bLength: HID Descriptor size */
    HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
    0x10,         /* bcdHID: HID Class Spec release number */
    0x01,
    0x00,         /* bCountryCode: Hardware target country 国家代码 */
    
	0x01,         /* bNumDescriptors: Number of HID class descriptors to follow
					 类别描述符数目(至少有一个报表描述符)*/
    0x22,         /* bDescriptorType 报告描述符 */
    CUSTOMHID_SIZ_REPORT_DESC,	/* wItemLength: Total length of Report descriptor 报告描述符大小 */
    0x00,						/* 标志类别描述符说明结束 */ 
	
	
/* 端点1描述符 */	
	/******************** Descriptor of Custom HID endpoints ******************/
    /* 27 */
    0x07,          /* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
 
    0x82,          /* bEndpointAddress: Endpoint Address (IN) */               
                   // bit 3...0 : the endpoint number
                   // bit 6...4 : reserved
                    // bit 7     : 0(OUT), 1(IN)
    0x03,          /* bmAttributes: Interrupt endpoint */
    0x40,          /* wMaxPacketSize: 64 Bytes max */
    0x00,
    0x02,          /* bInterval: Polling Interval (2 ms) */
    /* 34 */
 
/* 端点2描述符 */			
    0x07,	/* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE,	/* bDescriptorType: */
			/*	Endpoint descriptor type */
    0x01,	/* bEndpointAddress: */
			/*	Endpoint Address (OUT) */
    0x03,	/* bmAttributes: Interrupt endpoint */
    0x40,	/* wMaxPacketSize: 64 Bytes max  */
    0x00,
    0x02,	/* bInterval: Polling Interval (2 ms) */
    /* 41 */
}; /* CustomHID_ConfigDescriptor */
  • 0x09: 描述符的长度(9字节),这是整个配置描述符的大小。

  • USB_CONFIGURATION_DESCRIPTOR_TYPE: 描述符类型,对于配置描述符,这个值通常是0x02

  • CUSTOMHID_SIZ_CONFIG_DESC, 0x00: 总长度(Total Length)的低字节和高字节。wTotalLength字段表示整个配置描述符集的大小,包括所有接口、端点和设备类特定的描述符。这里只显示了低字节,高字节设置为0x00,意味着总长度不超过256字节。

  • 0x01: 接口数量(bNumInterfaces),表示这个配置中定义的接口数量为1。

  • 0x01: 配置值(bConfigurationValue),这是一个唯一的值,当主机请求设备改变配置时,它将使用这个值。

  • 0x00: 配置描述符字符串索引(iConfiguration),它指向一个字符串描述符,描述了这个配置。如果该值为0x00,则没有字符串描述符描述配置。

  • 0xC0: 属性(bmAttributes),这是一个位字段,用于描述配置的供电属性和其他特性:

    • 第7位(位7)设置为1,表示设备是总线供电的(Bus powered)。
    • 第6位(位6)设置为0,表示设备不是自供电的(Self powered)。
    • 第5位(位5)设置为0,表示设备不支持远程唤醒(Remote wakeup)。
    • 第4到第0位(位4…0)保留,必须设置为0
  • 0x96: 最大功耗(MaxPower),以2mA为单位的最大功耗值。0x96转换为十进制是150,所以最大功耗是150 * 2mA = 300mA。这表示设备在总线供电模式下最多可以消耗300mA的电流。

2.2 沁恒CH32V307代码

/* Configuration Descriptor(HS) */
const uint8_t  MyCfgDescr_HS[ ] =
{
    /* Configuration Descriptor */
    0x09,                           // bLength
    0x02,                           // bDescriptorType
    0x29, 0x00,                     // wTotalLength
    0x01,                           // bNumInterfaces
    0x01,                           // bConfigurationValue
    0x00,                           // iConfiguration (String Index)
    0x80,                           // bmAttributes
    0x23,                           // bMaxPower 70mA

    /* Interface Descriptor */
    0x09,                           // bLength
    0x04,                           // bDescriptorType (Interface)
    0x00,                           // bInterfaceNumber 0
    0x00,                           // bAlternateSetting
    0x02,                           // bNumEndpoints 2
    0x03,                           // bInterfaceClass
    0x00,                           // bInterfaceSubClass
    0x00,                           // bInterfaceProtocol
    0x00,                           // iInterface (String Index)

    /* HID Descriptor */
    0x09,                           // bLength
    0x21,                           // bDescriptorType
    0x11, 0x01,                     // bcdHID
    0x00,                           // bCountryCode
    0x01,                           // bNumDescriptors
    0x22,                           // bDescriptorType
    0x22, 0x00,                     // wDescriptorLength

    /* Endpoint Descriptor */
    0x07,                           // bLength
    0x05,                           // bDescriptorType
    0x01,                           // bEndpointAddress: OUT Endpoint 1
    0x03,                           // bmAttributes
    0x00, 0x02,                     // wMaxPacketSize
    0x01,                           // bInterval: 1mS

    /* Endpoint Descriptor */
    0x07,                           // bLength
    0x05,                           // bDescriptorType
    0x82,                           // bEndpointAddress: IN Endpoint 2
    0x03,                           // bmAttributes
    0x00, 0x02,                     // wMaxPacketSize
    0x01,                           // bInterval: 1mS
};
  • 0x09: 描述符的长度(9字节),这是整个配置描述符的大小。

  • 0x02: 描述符类型(bDescriptorType),对于配置描述符,这个值通常是0x02

  • 0x29, 0x00: 总长度(wTotalLength),表示整个配置描述符集的大小,包括所有接口、端点和设备类特定的描述符。这里0x29是低字节,0x00是高字节,所以总长度是0x0029(41字节)。

  • 0x01: 接口数量(bNumInterfaces),表示这个配置中定义的接口数量为1。

  • 0x01: 配置值(bConfigurationValue),这是一个唯一的值,当主机请求设备改变配置时,它将使用这个值。

  • 0x00: 配置描述符字符串索引(iConfiguration),它指向一个字符串描述符,描述了这个配置。如果该值为0x00,则没有字符串描述符描述配置。

  • 0x80: 属性(bmAttributes),这是一个位字段,用于描述配置的供电属性和其他特性:

    • 第7位(位7)设置为1,表示设备是自供电的(Self powered)。
    • 第6位(位6)设置为0,表示设备不是总线供电的(Bus powered)。
    • 第5位(位5)设置为0,表示设备不支持远程唤醒(Remote wakeup)。
    • 第4到第0位(位4…0)保留,必须设置为0
  • 0x23: 最大功耗(bMaxPower),以2mA为单位的最大功耗值。0x23转换为十进制是35,所以最大功耗是35 * 2mA = 70mA。这表示设备在自供电模式下最多可以消耗70mA的电流。

三、配置描述符组成详解

3.1 bLength

USB Configuration Descriptors 配置描述符的长度(一般长度为 9 字节)。

3.2 bDescriptorType

bDescriptorType 代表了本描述符的类型,设备描述符为 0x01。所有的描述符类型表示如下图,大家以后也可以速查:

3.3 wTotalLength

配置描述符集合总长度,也就是说总共有多少个字节。第二节讲了,配置描述符是以集合的形式,集合里包含了标准配置描述符,接口描述符,端点描述符,HID 描述符,wTotalLength 就是配置描述符集合的长度。

  

3.4 bNumInterfaces

当前配置下面有多少个接口,单一功能设备只有一个接口,如鼠标或者键盘,如果是复合设备,如果是鼠键一体的设备,那么它可能有两个接口,其实一个接口对应于一种功能,如果我们在软件实现的时候,把鼠标键盘当做一个功能实现的时候,那就是一个接口的设备(也就是单功能设备)。

3.5 bConfigurationValue

前面说了,一个 USB 设备可能有多个配置,但是当前只能选择一种配置。bConfigurationValue 就是当前配置的标识,如果主机想选择哪种配置,是通过标识去选择的,后面枚举的时候会详细讲解。

3.6 iConfiguration

描述该配置的字符串的索引值,如果没有字符串,那这个值就是 0。

3.7 bmAttributes

在这个配置下,设备的一些特性。D7 是保留位,默认为 1;D6 表示供电方式,0 是自供电,1 是总线供电;D5 表示是否支持远程唤醒,为 1 表示设备支持远程唤醒;D4~D0 保留,默认为 0。大家可能会问为什么不把这些特性放在设备描述符里面,这些可都是设备的属性啊,在这里要告诉大家,USB设备会有多种配置,每种配置下的设备属性是不一样的,主机可以灵活的选择使用那种配置,从而实现对应配置上的功能,这样增加了总线设计的灵活性和可配置性,从而达到通用性。

Keyboard 和 Mouse 等消费电子可能需要将该参数项设置为支持远程唤醒!

3.8 bMaxPower

在这个配置下,设备需要的电流,单位是 2ma。如果一个设备耗电量 100ma,那么本字节设置为 0x32 即可。

四、粉丝交流群

嵌入式交流群 1 群:958820627(可能已满);嵌入式交流群 2 群:876919359(可能已满);嵌入式交流群 3 群:957431539(推荐加入)。欢迎加群,有问题可以群内分享技术交流,秋招和春招会有诸多大厂内推码或者内推名额推荐。希望大家友好讨论技术知识!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2048865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【工业机器人】工业异常检测大模型AnomalyGPT

AnomalyGPT 工业异常检测视觉大模型AnomalyGPT AnomalyGPT: Detecting Industrial Anomalies using Large Vision-Language Models AnomalyGPT是一种基于大视觉语言模型(LVLM)的新型工业异常检测(IAD)方法。它利用LVLM的能力来理…

Oracle VM VirtualBox虚拟机内存不够用的解决方案

一、 前言 在使用Oracle VM VirtualBox虚拟机的过程中,随着时间的推移,我们会感觉我们的内存越来越不够用,今天就来给大家分享一下我们如何解决虚拟机内存不够用的问题。 二、解决方法 1.虚拟机碎片化整理 我们第一步要做的是碎片整理&…

【protobuf】ProtoBuf——proto3语法详解、enum类型、enum类型的使用和注意事项、Any类型、通讯录录入号码类型和地址的功能实现

文章目录 ProtoBuf5. proto3语法详解5.3 enum类型5.4 Any类型 ProtoBuf 5. proto3语法详解 5.3 enum类型 定义规则: proto3支持我们定义枚举类型并使用: 枚举类型的名称采用驼峰命名法且首字母大写,如 MyEnum ,这样的命名方式符合…

重启人生计划-且随风行

🥳🥳🥳 茫茫人海千千万万,感谢这一刻你看到了我的文章,感谢观赏,大家好呀,我是最爱吃鱼罐头,大家可以叫鱼罐头呦~🥳🥳🥳 如果你觉得这个【重启人生…

Element UI详解

目录 Element UIElement UI 简介开发使用开发指南概述总结 设计原则组件使用特性使用场景优势不足 Element UI Element UI 简介 Element UI 是由饿了么前端团队开发的一套基于 Vue.js 的桌面端组件库。它提供了一系列丰富的 UI 组件,用于快速搭建企业级的 Web 应用…

RCE编码绕过--php://filter妙用

目录 代码 如何绕过 payload构造 代码 <?php $content <?php exit; ?>; $content . $_POST[txt]; file_put_contents($_POST[filename],$content); 当你想要输入代码的时候前面会有<?php exit;?>;&#xff0c;代码没有办法执行下去&#xff0c;所以…

day32+学习记录

一.算法练习 509.斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xf…

(待会删)分享9款一键生成原创论文在线使用软件

在当前的学术研究和写作环境中&#xff0c;AI技术的应用已经变得越来越普遍。其中&#xff0c;一键生成原创论文的在线软件更是为学者们提供了极大的便利。本文将重点介绍一款备受推荐的AI原创论文写作平台——千笔-AIPassPaPer&#xff0c;并分享其他几款优秀的同类软件。 千…

政务大数据解决方案(五)

政务大数据解决方案旨在通过建立统一的数据平台&#xff0c;将各政府部门的数据资源进行有效整合与智能分析&#xff0c;利用先进的数据处理和人工智能技术实现对社会动态的实时监测和精准预测&#xff0c;从而优化政府决策、提升公共服务效率和透明度。该方案涵盖数据的采集、…

每日OJ_牛客HJ75 公共子串计算

目录 牛客HJ75 公共子串计算 解析代码 牛客HJ75 公共子串计算 公共子串计算_牛客题霸_牛客网 解析代码 求最大公共子串&#xff0c;使用递推实现 假设 x(i)&#xff1a;字符串第i个字符 y(j)&#xff1a;字符串第j个字符 dp[i][j]&#xff1a;以x(i)&#xff0c;y(j)结尾的最…

XSS-games

XSS 1.XSS 漏洞简介2.XSS的原理3.XSS的攻击方式4.XSS-GAMESMa SpaghetJefffUgandan KnucklesRicardo MilosAh Thats HawtLigmaMafiaOk, BoomerWW3svg 1.XSS 漏洞简介 ​ XSS又叫CSS&#xff08;Cross Site Script&#xff09;跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Sc…

XSS反射实战

目录 1.XSS向量编码 2.xss靶场训练&#xff08;easy&#xff09; 2.1第一关 2.2第二关 方法一 方法二 2.3第三关 2.4第四关 2.5第五关 2.6第六关 2.7第七关 第一种方法&#xff1a; 第二种方法&#xff1a; 第三个方法&#xff1a; 2.8第八关 1.XSS向量编码 &…

二叉树进阶之二叉搜索树:一切的根源

前言&#xff1a; 在学完了简单的容器与C面向对象的三大特性之后&#xff0c;我们首先接触的就是map与set两大容器&#xff0c;但是这两个容器底层实现的原理是什么呢&#xff1f;我们不而知&#xff0c;今天&#xff0c;主要来为学习map与set的底层原理而打好基础&#xff0c…

【精选】学生考勤管理系统设计与实现(源码+辅导+设计)

目录&#xff1a; 系统介绍&#xff1a; 第2章 开发技术介绍 2.1 B/S结构 2.2 Java语言 2.3 springboot框架 2.4 MySQL数据库 系统设计 系统的总体功能设计 系统实现界面&#xff1a; 3.视频演示 系统测试 测试概述 测试结果 参考代码&#xff1a; 为什么选择我&am…

【数据结构】PTA 单链表逆转 C语言

本题要求实现一个函数&#xff0c;将给定的单链表逆转。 函数接口定义&#xff1a; List Reverse( List L ); 其中List结构定义如下&#xff1a; typedef struct Node *PtrToNode; struct Node {ElementType Data; /* 存储结点数据 */PtrToNode Next; /* 指向下一个结点的…

进程间通信学习记录(IPC 机制以及共享内存)

0.System V IPC机制&#xff1a; ①.IPC对象包含&#xff1a;共享内存、消息队列和信号灯集。 ②.每个IPC对象有唯一的ID。 ③.IPC对象创建后一直存在&#xff0c;直到被显示地删除。 ④.每一个IPC对象有一个关联的KEY。&#xff08;其他进程通过KEY访问对应的IPC对象&#xff…

XSS和DOM破坏案例

XSS案例 环境地址&#xff1a;XSS Game - Learning XSS Made Simple! | Created by PwnFunction 1.Ma Spaghet! 源码&#xff1a; <!-- Challenge --> <h2 id"spaghet"></h2> <script>spaghet.innerHTML (new URL(location).searchParam…

【LiteX】【开发板】【BoChenK7】使用Python开发FPGA【SDRAM/DDR/Bootloader】

目录 开发板介绍下载仓库工程设计代码实现 工程构建启动测试Memory测速Bootloader&#xff08;裸机BareMetal程序&#xff09;Bootloader&#xff08;Linux OS&#xff09; 开发板信息 开发板介绍 手头目前只有一个购买的BoChenK7开发板&#xff0c;后续会用它来进行LiteX FPG…

政务大数据解决方案(九)

政务大数据解决方案旨在通过构建高效的数据处理与分析系统&#xff0c;全面整合政府各部门数据资源&#xff0c;运用尖端技术进行深入挖掘与智能分析&#xff0c;为政府决策提供科学、精准的数据支撑&#xff0c;优化政策制定与执行流程&#xff0c;同时通过加强数据安全与隐私…

基于Kotlin Multiplatform实现静态文件服务器(一)

本文将介绍如何基于Kotlin Multiplatform、Jetpack Compose实现静态文件服务器&#xff0c;并运行在Android、Windows以及Linux&#xff08;暂不支持server和mac&#xff09;。 创建KMP&#xff08;Kotlin Multiplatform&#xff09;项目 环境设置 安装Android Studiio 2023.…