透彻理解USB总线应用之枚举
Hello,大家好,今天我们来讨论一下USB总线中的枚举(Enumeration),首先简单介绍一下USB系统的基本架构,它由USB主机、USB设备与USB电缆(本文忽略它)组成,如下图所示:

最常见的主机就是电脑了,现在很多有USBOTG(On-The-Go)功能的手机也可以做主机,无需过多赘述。USB设备实在太多了,例如,手机、MP4、U盘、移动硬盘、打印机、扫描仪等等,当然,作为工程师的你还可能会购买其它一些使用USB接口的仪器,例如逻辑分析仪,示波器等等。无论USB设备的具体形式是怎么样的,按照功能都可以分为两大类,其中之一就是USB功能设备。刚刚提到的USB设备都属于这类,它们都各自提供了一些特定的功能,例如,U盘就是存储数据,示波器就是采集数据。
另外一类USB设备就是USB集线器(USB Hub),它的功能与网络集线器相同,把一个USB接口扩展多个USB接口。例如,学校一个寝室有很多人,每个人都有一台电脑,但网线只有一根,怎么办?用网络集线器就可以解决这个问题,如下图所示

我们只需要特别留意:USB系统的数据或指令传输都是由主机启动的,USB设备只是根据主机的要求进行被动响应。在任意时刻,USB系统仅允许存在一个USB主机。
------------------------------------------------------------------------------------------------------
好的,现在有一个问题得先弄明白:为什么在电脑同一个USB接口依次插入鼠标、键盘或其它USB设备,电脑都能够正确地识别它的功能呢?这就是枚举的功劳。为了形象地理解枚举,我们来看一个面试对话场景:
------------------------------------------------------------------------------------------------
面试官:我看你的简历上说对三极管有比较深入的了解,那么请形象地讲讲三极管的放大原理。
你:好的,你可以把三极管的三个区比作三个国家,然后…..
面试官:这个故事是你自己总结的吗?
你:不瞒你说,是通过微信公众号《电子制作站》学来的。
面试官莞尔一笑:是嘛 ,难怪我怎么觉得这么熟悉,那另外一篇关于上下拉电阻的文章你看过没有?
你:必须的呀!
面试官:那你说说拉电流与灌电流的区别?
你:拉与灌只是电流方向不同而已,具体到电路结构,就是…..
…..
面试官:好的,我觉得你的水平确实不错,至少基础非常扎实,不愧是关注《电子制作站》微信公众号的老粉,值得信赖….
….
然后你就顺利进入了该公司,拿到了一个代表你是公司员工的工牌….
----------------------------------------------------------------------------------------------------------
在以上面试过程中,面试官首先提出一个问题,根据面试者的反馈后再跳到另一个知识点,依此循环,继而完成全面考察面试者业务水平的目的,最后才决定是否符合公司的录用标准,这其实就是一个枚举的过程。在面试的场景中,你就是USB设备,面试官就是USB主机,所以简单的说,枚举就是“识别”的同义词。
同样的道理,当USB鼠标插入到电脑时,电脑也需要询问关于它的一些信息,以确定它到底是个什么东东。电脑当然是不能说话的,它只是会发送一些命令,USB设备必须对这些命令进行响应,不然枚举就会失败(问你话咋一声不吭呢?面试失败!)。当然,USB设备必须进行正确响应,乱来也会导致枚举失败(回答问题怎么牛头不对马嘴呢?面试失败!)。当然,即便枚举成功了,也不一定代表USB设备能用,枚举成功只是万里长征的第一些。(你小子面试时能说会道,做起实事来却完全不顶用,明天卷铺盖滚蛋吧,赶紧从我眼前消失!失败中的失败!!)
概括来讲,如果我们开发自己的USB设备,关键的两个步骤是必须进行的。
其一:让USB设备按照USB协议正确回应主机的命令,以成功完成枚举。
其二:在枚举成功后,把数据按正确的格式进行传输。
有些人想:虾米?还要响应命令呐,粗看了一下,貌似很复杂,玩不了,回家洗洗睡了!哈哈,必须得打击你一下,USB底层的实现确实有点复杂,但幸运的是,通常厂商都会把底层核心的东西做好了打包成库,我们只要修改一些应用方面的数据即可。也就是说,如果你只是使用USB总线传输数据,底层的东西你没机会(也不需要)去修改。
那到底需要修改什么才能成功完成枚举呢?其实道理跟我们工程师做项目一样!例如使用单片机控制新的器件时,第一步需要做的就是了解新器件的基本原理,包括通讯时序、寄存器的定义、硬件电路的连接要求等等。器件厂家为了方便用户使用,通常都会准备好相应的数据手册(datasheet),它包含了用户应用该器件的所有信息。
同样的道理,如果把你当成一台电脑,当USB鼠标插入USB接口时,你又是怎么知道它是鼠标,而不是键盘或其它设备呢?很明显,你(电脑)也需要数据手册之类能够描述插入设备所有信息的媒介,对不对?USB协议中定义的描述符(descriptor)就是这个目的。
描述符在C语言实现层面通常就是结构体(Structure),应用上就是多个有一定关联的信息的集合体。例如,我要定义一个员工的描述符,它应该包含姓名、性别、年龄、工号等等信息,如下所示:

也就是说,USB描述符就是用来描述相应的USB设备具体是什么,有什么特点,能做什么(是不是真的能做就不知道了),所以在源代码编程自定义USB设备时,我们最先开始的工作就是:找到厂商提供的固件(firmware)或示例程序中描述符对应的位置,再根据USB协议的规定进行合适的修改。如果修改正常,厂商提供的固件会自动根据主机发送的命令提交你修改描述符信息,这样主机才能正确识别(会提示你插入了新设备,可以正常使用了),至于它具体能不能起到什么功能,就是枚举成功之后再去讨论的事了,先通过面试这一关才能发挥咱们的才干呐!
USB协议定义了很多描述符,结构也远比前面的员工信息要复杂的多,我们将在下一篇文章中继续讨论,么么哒~~
透彻理解USB总线应用之枚举的更多相关文章
- Linux驱动之USB总线驱动程序框架简析
通用串行总线(USB)是主机和外围设备之间的一种连接.USB总线规范有1.1版和2.0版,当然现在已经有了3.0版本.USB1.1支持两种传输速度:低速为1.5Mbps,高速为12Mbps.USB2. ...
- EDK II之USB总线驱动的实现框架
本文简单介绍一下UEFI中USB驱动的实现框架: 下图是USBD向上层驱动提供的接口: 1.从图中我们可以看出,USBDI的实现主要通过调用HCDI实现 和 访问USB_INTERFACE结构体(该结 ...
- Linux下的USB总线驱动(一)
版权所有,转载请说明转自 http://my.csdn.net/weiqing1981127 一.USB理论 1. USB概念概述 USB1.0版本速度1.5Mbps(低速USB) USB1 ...
- 回调函数透彻理解Java
http://blog.csdn.net/allen_zhao_2012/article/details/8056665 回调函数透彻理解Java 标签: classjavastringinterfa ...
- USB总线介绍
•USB 1.0出现在1996年的,速度只有1.5Mb/s1998年升级为USB 1.1,速度也提升到12Mb/s,称之为”full speed” •USB2.0规范是由USB1.1规范演变而来的.它 ...
- USB总线标准
1.USB总线类型: OHCI(Open Host Controller Interface)是支持USB1.1的标准,但它不仅仅是针对USB,UHCI(Universal Host Controll ...
- linux usb总线驱动(一)
目录 linux usb总线驱动框架 USB 介绍 传输类型 控制器接口 2440接口 基本流程 alloc_dev choose_address hub_port_init usb_get_devi ...
- 透彻理解Spring事务设计思想之手写实现
前言 事务,是描述一组操作的抽象,比如对数据库的一组操作,要么全部成功,要么全部失败.事务具有4个特性:Atomicity(原子性),Consistency(一致性),Isolation(隔离性),D ...
- Spark2.1.0——深入理解事件总线
Spark2.1.0——深入理解事件总线 概览 Spark程序在运行的过程中,Driver端的很多功能都依赖于事件的传递和处理,而事件总线在这中间发挥着至关重要的纽带作用.事件总线通过异步线程,提高了 ...
随机推荐
- MFC Object 与 Windows Object
MFC Object 和 Windows Object的含义 Window Object(Window对象)是Win32下用句柄表示的Windows操作系统对象.MFC Object(MFC对象)是C ...
- 『政善治』Postman工具 — 11、Postman中对Cookie的操作
目录 1.关联接口说明 2.测试关联接口实现步骤 3.补充:Postman中将请求转换成代码 上一篇文章说明了Postman中关于Cookie的相关操作,还是以Cookie举例,来说明下一在Postm ...
- C++ primer plus读书笔记——第12章 类和动态内存分配
第12章 类和动态内存分配 1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形或枚举型const,则可以在类声明中初始化 ...
- Fiddler抓包工具使用记录
前言 Fiddler是一款强大的Web调试代理工具,又称抓包软件,本文记录如何使用Flidder进行抓包 Fiddler官网:https://www.telerik.com/fiddler 下载安装 ...
- CRM系统全方位管理企业
您在选择一款CRM系统的时候,首先要考虑销售团队的感受和意见.让CRM系统在帮助销售团队优化工作流程的同时,更好地对销售团队进行管理.销售人员每卖出一件商品,要从寻找筛选商机开始,经过沟通客户需求.满 ...
- 云服务器Apache+MySQL(远程连接)+PHP等环境安装2021.5.9号配置
云服务器Apache+MySQL(远程连接)+PHP等环境安装2021.5.9号配置 Linux版本:centos8.2 (其他版本提供适配) 安装方式:yum 今天使用centos8系统搭建了下云主 ...
- Python 库整理【收藏】
库名称简介 Chardet字符编码探测器,可以自动检测文本.网页.xml的编码. colorama主要用来给文本添加各种颜色,并且非常简单易用. Prettytable主要用于在终端或浏览器端构建格式 ...
- 云计算OpenStack共享组件---信息队列rabbitmq(2)
一.MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们. 消息传 ...
- SSTI漏洞-fastapi
0x00 原理 SSTI漏洞全称服务器模板注入漏洞,服务器模板接收了用户输入的恶意代码,未经过滤便在服务端执行并通过渲染模板返回给用户,使得用户可以通过构造恶意代码在服务端执行命令. 0x01 c ...
- RedisPool
class RedisPool(object): instance = None def __init__(self, host='192.168.2.129', port=7000, passwor ...