USB子系统简述

news2024/11/29 2:40:40

引子:关于 lsusb 命令

lsusb 列出系统中所有的USB设备:

Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

Bus 004 :表示第四个 usb 主控制器(机器上总共有四个 usb 主控制器,可以通过命令 lspci | grep USB 查看)。

Device 001表示系统给 usb 鼠标设备分配的设备号(devnum),同时也可以看到该设备是插入到了第4个 usb 主控制器。

ID 1d6b:0003 表示 usb 设备的 ID(这个 ID 由芯片制造商设置,可以唯一表示该设备)。可在 /sys/devices/pci0000:00/0000:[]:][][.[]/usbx/x-x/ 目录下查看 devnum、idVendor、idProduct 等信息。

最后面的 root hub 应该是代表 该设备是挂载在跟集线器


lsusb -v 列出系统中所有的USB设备的各个描述符信息:

Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Couldn't open device, some information will be missing
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               3.00
  bDeviceClass            9 Hub
  bDeviceSubClass         0 Unused
  bDeviceProtocol         3 
  bMaxPacketSize0         9
  idVendor           0x1d6b Linux Foundation
  idProduct          0x0003 3.0 root hub
  bcdDevice            4.04
  iManufacturer           3 
  iProduct                2 
  iSerial                 1 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           31
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xe0
      Self Powered
      Remote Wakeup
    MaxPower                0mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         9 Hub
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0 Full speed (or root) hub
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0004  1x 4 bytes
        bInterval              12
        bMaxBurst               0

...

这里代表的是 这USB设备的 四个描述符:设备、配置、接口、端点 的描述信息

一 设备、配置、接口、端点、及其描述符、管道、URB

端点:struct usb_host_endpoint

端点是USB通信的最基本形式,每一个USB设备在主机看来就是一个端点的集合,因为主机只能通过端点与设备进行通信,每个端点都有唯一的地址,由设备号和端点号给出。每个端点都有一定的属性,包括传输方向,总线访问频率,带宽,端点号,数据包最大容量等信息。一个端点只能在一个方向上承载数据,从主机到设备(输出端点),或者从设备到主机(输入端点),因此端点可以看做是一个单项的管道。端点0通常作为控制端点,用于设备初始化参数等。只要设备连接到USB上并上电,端点0就可以被访问。端点1、2 通常作为数据端点,用于主机与设备之间数据往来。

接口: struct usb_interface
接口由多个端点组成,其中端点我们知道可以看作一个单项的数据管道,即单项的数据通道。那么众多端点汇集成的接口 就形成了一个基本功能,所以接口就代表一个基本的功能,是USB设备驱动程序控制的对象,一个功能复杂的USB设备可以具有多个接口,即多个功能。另外每个接口可以有备用接口,一提供不同质量的服务参数。

配置:struct usb_host_config
由众多接口汇集而成,那么配置可以理解为是 功能集,包含选择的若干功能。一个配置中的所有借口可以同时有效,即所有功能可以同时工作。

设备:usb_device 代表一个usb设备

USB标准定义了一系列的 描述符数据结构来保存设备的信息。Linux-USB核心定义的描述符有四种类型。

设备描述符:存放设备的普通信息 如产品ID、设备ID等 — struct usb_device_descriptor

配置描述符:描述设置的配置模式信息,如设备是总线供电还是自己供电 ---- struct usb_config_descriptor

接口描述符:使得USB设备能支持多种功能 ---- struct usb_interface_descriptor

端点描述符:描述端点信息 ---- struct usb_endpoint_descriptor

打印设备上的全部端点地址:

//USB device
struct usb_device *udevice;
//USB设备描述符
struct usb_device_descriptor u_d_desc = udevice->descriptor

//USB 配置
struct usb_host_config *uconfig;
///USB 配置描述符
struct usb_config_descriptor U_c_desc;

//接口
struct usb_interface *uinterface;
//接口设置
struct usb_host_interface *ualtsetting
//接口描述符
struct usb_interface_descriptor u_i_desc;

//USB 端点
struct usb_host_endpoint *uendpoint;
//USB 端点描述符
struct usb_endpoint_descriptor u_e_desc;


//获取配置
uconfig = udevice->actconfig;
//获取配置描述符
U_c_desc = uconfig->desc;

//遍历配置(功能集)中的所有接口(功能)
for(int i=0; i<U_c_desc.bNumInterfaces; i++){
	
	//获取接口
	uinterface = udevice->actconfig->interface[i];
	//遍历所有备用设置
	for(int j=0; j<uinterface->num_altsetting; j++){
		//获取备用甚设置
		ualtsetting = &uinterface->altsetting[j];
		//获取接口描述符
		u_i_desc = ualtsetting->desc;
		
		//遍历接口下的所有端点
		for(int k=0; k<u_i_desc.bNumEndpoints; k++){
			//获取端点
			uendpoint = &ualtsetting->endpoint[k];
			//获取端点描述符
			u_e_desc = uendpoint->desc;
			//打印端点地址
			printk("Endpoint Address = %d\n",u_e_desc.bEndpointAddress);
		}
	}
	
}

关系如下:

//usb 设备
struct usb_device 
	//设备描述符
	struct usb_device_descriptor descriptor;
	//配置
	struct usb_host_config *actconfig;
		//USB 配置描述符
		struct usb_config_descriptor	desc;
		//接口集(功能集)
		struct usb_interface *interface[USB_MAXINTERFACES];
			//当前激活的备用设置
			struct usb_host_interface *cur_altsetting;	
			//备用设置数组
			struct usb_host_interface *altsetting;
				//接口描述符
				struct usb_interface_descriptor	desc;
					//端点数量
					__u8  bNumEndpoints;
				//端点数组
				struct usb_host_endpoint *endpoint;
					//端点描述符
					struct usb_endpoint_descriptor		desc;
						//端点地址
						__u8  bEndpointAddress;
			//备用设置数量
			unsigned num_altsetting;	

URB: USB数据传输机制使用的核心数据结构。URB供USB协议栈使用:struct urb

管道: 管道包括以下几个部分:

端点地址
数据传输方向(IN或OUT)
数据传输模式(控制模式,中断模式,批量模式,等时模式)

管道是URB的重要成员,为USB数据传输提供地址信息。

二 Linux USB 子系统

如下图是 Linux USB 子系统的架构。该子系统由以下几个部分组成:

在这里插入图片描述

USB核心:USB核心由一些基础代码组成,这些基础代码包括结构体和函数定义,供HCD和客户驱动程序使用,同时也间接的使得客户驱动与具体的主控制器无关。

驱动不同主机控制器的 HCD

用于根集线器(包括物理集线器)的Hub驱动和一个内核辅助线程 khubd。khubd监视与该集线器连接的所有端口。系统检测端口状态变化以及配置热拔插设备是很消耗时间的事情,而内核提供的基础设施辅助线程就能很好的完成这些任务。通常情况下,该线程处于休眠状态。当集线器驱动程序检测到USB端口状态变化后,该内核线程立马被唤醒。

用于USB客户设备的设备驱动程序

USB文件系统usbfs,能够让你从用户空间驱动USB设备。

三 关于集线器枚举

枚举过程是热拔插USB设备的起始步骤,该过程中,主机控制器最终会获得设备的相关信息并配置好设备。在USB子系统中,集线器驱动程序负责该枚举过程。如将USB笔驱动器插入主机后,设备的枚举分一下几步执行。

1 根集线器报告插入设备导致的端口电流变化,集线器驱动程序检测到这一变化(在Linux-USB里称为 USB_PORT_STAT_C_CONNECTION),唤醒 khubd线程。

2 khubd识别出电流变化在哪个端口,即我们的设备插入的端口

3 接着khubd线程再 1~127中挑选一个数分配给笔驱动器的批量端点,这是通过控制端点0发送控制URB来实现的。

4 khubd线程利用端口0使用的控制URB从笔驱动器设备获取设备描述符,配置描述符。

5 khubd线程请求USB核心把对应的客户驱动程序和该USB设备挂钩。当枚举过程完成后,驱动程序和设备也已经绑定好了,khubd线程就会调用相关客户驱动程序的probe()函数。这里, khubd线程调用的是 storage_probe()。

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

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

相关文章

看完这篇文章终于弄明白了什么是 RocketMQ 的存储模型

RocketMQ 优异的性能表现&#xff0c;必然绕不开其优秀的存储模型 。这篇文章&#xff0c;笔者按照自己的理解 , 尝试分析 RocketMQ 的存储模型&#xff0c;希望对大家有所启发。1 整体概览首先温习下 RocketMQ 架构。整体架构中包含四种角色 :Producer &#xff1a;消息发布的…

基于Python深度学习的垃圾分类代码,用深度残差网络构建

垃圾分类 完整代码下载地址&#xff1a;基于Python深度学习的垃圾分类代码 介绍 这是一个基于深度学习的垃圾分类小工程&#xff0c;用深度残差网络构建 软件架构 使用深度残差网络resnet50作为基石&#xff0c;在后续添加需要的层以适应不同的分类任务模型的训练需要用生…

Qt扫盲-QSerialPort理论总结

QSerialPort理论总结一、概述二、使用流程1. 错误处理2. 阻塞串行端口编程3. 非阻塞串行端口编程三、信号四、注意事项一、概述 QSerialPort 类其实就是一个打开串口&#xff0c;进行串口通信传输数据的功能类。我们可以使用QSerialPortInfo帮助类获取有关可用串行端口的信息&…

JavaEE高阶---Spring AOP

一&#xff1a;什么是Spring AOP&#xff1f; 首先&#xff0c;AOP是一种思想&#xff0c;它是对某一类事情的集中处理。 如用户登录权限的效验&#xff0c;没学 AOP 之前&#xff0c;我们所有需要判断用户登录的页面&#xff0c;都要各自实现或调用验证的方法。然后有了 AOP …

【Linux进程间通信】

Linux进程间通信进程间通信介绍进程间通信的概念进程间通信的目的进程间通信的本质进程间通信的分类管道什么是管道匿名管道匿名管道的原理pipe函数匿名管道使用步骤匿名管道读写规则匿名管道的特点匿名管道的四种特殊情况匿名管道的大小命名管道命名管道的原理使用命令创建命名…

【浮点数在内存中的存储规则】

我们知道&#xff0c;整型在内存中的存储比较简单&#xff0c;在内存中都是以二进制来存储的。然而&#xff0c;浮点型在内存中的存储较为复杂。下面来详细探讨&#xff1a; 直接举一个例子&#xff1a; int main() { int n 9; float *pFloat (float *)&n; printf("…

工业树莓派解决传统数据设备数据上云问题

一、前言 工业4.0的浪潮下&#xff0c;许多中小型制造业企业渴望通过数字化转型谋求新的发展动力&#xff0c;然而&#xff0c;在转型之路上常常会面临一个问题&#xff1a;传统数据采集设备数量多、种类杂&#xff0c;不支持比较新颖的现场总线协议或者通信技术&#xff0c;最…

java 微服务框架介绍 SpringCloud Eureka注册中心 Nacos注册中心

为什么要学习微服务框架 认识微服务 服务架构演变 单体架构 分布式架构 微服务结构 SrpingCloud SpringCloud是目前国内使用最广泛的微服务框架。官网地址&#xff1a;https://spring.io/projects/spring-cloud。 服务拆分及远程调用 服务拆分注意事项 我们查询的时候需要…

Java基础 —— 编程入门

一、比特(bit)和字节(byte)一个0或者一个1存储为一个比特(bit)&#xff0c;是计算机中最小的存储单位。计算机中是最基本的存储单元是字节(byte)。每个字节由8个比特构成。计算机就是一系列的电路开关。每个开关存在两种状态:关(off)和开(on)。如果电路是开的&#xff0c;它的值…

Ubuntu物理真机提高访问速度

这里不适合小白用户&#xff0c;只是做出几点提醒。 iguge学术助手 纯Ubuntu真机&#xff0c;是没办法访问外部网络的&#xff0c;先用百度搜索iguge下载一个&#xff0c;安装在Firefox浏览器插件上&#xff08;edge或者chrome也行&#xff09;。 免费的不好用&#xff0c;建…

算法之初始动态规划

目录 前言&#xff1a; 初始动态规划 0-1背包问题 0-1背包问题升级版 问题&#xff1a;如何巧妙解决“双十一”购物是的凑单问题&#xff1f; 总结&#xff1a; 前言&#xff1a; 淘宝的“双十一”购物节有各种促销活动&#xff0c;比如“满 200 元减 50 元”。假设你女朋友…

SpringBoot使用 axis 实现webservice客户端(亲测可行)

目录一、webservice在线验证服务端接口地址二、使用 axis 实现webservice客户端代码示例2.1、服务端地址使用qq在线接口验证接口2.2、webservice客户端示例代码一、webservice在线验证服务端接口地址 qq 在线验证接口&#xff1a;http://www.webxml.com.cn/webservices/qqOnli…

[飞腾]Trace32使用概述

最近将多年来收集到的教学视频、国内外图书、源码等整理整合拿出来&#xff0c;涉及arm、Linux、python、信号完整性、FPFA、DSP、算法、stm32、单片机、制图、电子模块、kali、出版社图书等。资料目前约1.5TB。资料详情请参阅&#xff1a; 1.5TB电子工程师资料详细介绍https:/…

软件定义的存储时代即将结束

数据存储、安全性、保护和整体管理对于大多数组织的生存至关重要。 从软件定义的存储时代的结束到本地存储的回归&#xff0c;Nyriad的首席营收官概述了他对最新技术趋势的看法&#xff0c;并提供了他对2023年将会发生的预测。 从以CPU为中心的软件定义存储过渡到卸载辅助架构…

Java 开发环境配置 || Java 基础语法

Java 开发环境配置 在本章节中我们将为大家介绍如何搭建Java开发环境&#xff0c;以及不同系统下的环境变量怎么配置。 window系统安装java 下载JDK 首先我们需要下载java开发工具包JDK&#xff0c;下载地址&#xff1a;Java Downloads | Oracle 点击如下下载按钮&#xff…

阿里CCO:基于Hologres的亿级明细BI探索分析实践

作者&#xff1a;张乃刚&#xff08;花名&#xff1a;隽驰)&#xff0c;CCO数据开发 CCO是Chief Customer Officer的缩写&#xff0c;也是阿里巴巴集团客户体验事业部的简称。随着业务的多元化发展以及行业竞争的深入&#xff0c;用户体验问题越来越受到关注。CCO体验业务运营…

【前端】CSS进阶

四、选择器进阶 1.1后代选择器&#xff1a;空格 作用&#xff1a;根据HTML标签的嵌套关系&#xff0c;选择父元素后代中满足条件的元素 选择器语法&#xff1a;选择器1 选择器2{css} 结果&#xff1a; 在选择器1所找到标签的后代&#xff08;儿子、孙子、重孙子…&#xf…

Zipkin基础知识及Linux下搭建服务端

Zipkin组成 Zipkin的基础架构&#xff0c;他由4个核心组件构成&#xff1a;分别是Collector、Storage、RESTful API、WebUI Collector&#xff1a;收集器组件&#xff0c;它主要用于处理从外部系统发送过来的跟踪信息&#xff0c;将这些信息转换为 Zipkin 内部处理的 Span 格式…

最快速的获取元素的方法?快到你想象不到~

1、首先我们先准备一个div标签&#xff0c;id定义为box<div id"box"></div>2、通常情况下我们会使用原生js获取&#xff0c;如下所示&#xff1a;let box document.getElementById("box"); // 或者 let box document.querySelector("#b…

【Vue中使用Echarts】Echarts的基本配置

文章目录一、Echarts的基础配置二、柱状图表1.原始柱状图2.经过美化的柱状图3.横向柱状图一、Echarts的基础配置 需要了解的主要配置&#xff1a;series xAxis yAxis grid tooltip title legend color 属性作用series系列列表。每个系列通过 type 决定自己的图表类型 大白话&am…