USB子系统简述

引子:关于 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()。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值