Linux驱动框架——USB驱动简单分析

本文介绍了Linux中的USB驱动框架,包括USB设备基础知识如端点、接口和配置,以及USB驱动框架源码分析。Linux内核提供了USB core来处理复杂的USB设备交互,驱动通过USB驱动框架与主机控制器和硬件设备进行通信。USB端点分为控制、中断、批量和等时传输四种类型。USB设备的接口和配置在内核中由特定结构体描述。通过对`usb_skeleton.c`的分析,揭示了USB驱动的注册、匹配和设备操作过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux驱动框架——USB驱动

​ 通用串行总线USB(Universal serial bus)通常用于外围设备与主机之间的连接,USB使用树型结构,主机作为根,集线器作为节点,外围设备作为树叶。

​ Linux当前支持几乎所有USB类设备(标准类型的设备,如键盘,鼠标,调制解调器,打印机和扬声器),以及越来越多的特定于供应商的设备(如USB到串行转换器,数码相机,以太网设备和MP3播放器等)。

​ 也有一部分USB设备是Linux不支持的,这些设备一般都是由供应商单独开发协议,大部分会开放协议给驱动人员开发使用。

​ 由于不同的通信协议都需要自定义创建新的驱动程序,因此Linux开发者开发了一套USB驱动通用框架,它是源码中的drivers/usb/usb-skeleton.c。

​ USB设备很复杂(http://www.usb.org)。幸运的是Linux内核提供了一个叫做USB core的驱动子系统处理大多数的复杂情况。如下图,USB Core向上提供给驱动接口,让驱动可以简单的对USB主机控制器进行控制操作,从而对USB硬件设备进行控制操作。

NycR4e.png

USB设备基础知识

下面介绍Linux中USB设备的组织结构。

Nycvgs.png

端点Endpoint

USB的通过端点来进行通信,USB的端点类似于单向管道,它的通信是单工的。USB的端点一共有以下四种类型:

控制传输

控制传输主要用于向设备发送配置信息、获取设备信息、发送命令道设备,或者获取设备的状态报告。控制传输一般发送的数据量较小,当USB设备插入时,USB核心使用端点0对设备进行配置,另外,端口0与其他端点不一样,端点0可以双向传输。

中断传输

中断传输就是中断端点以一个固定的速度来传输较少的数据,USB键盘和鼠标就是使用这个传输方式。这里说的中断和硬件上下文中的中断不一样,它不是设备主动发送一个中断请求,而是主机控制器在保证不大于某个时间间隔内安排一次传输。中断传输对时间要求比较严格,所以可以用中断传输来不断地检测某个设备,当条件满足后再使用批量传输传输大量的数据。

批量传输

批量传输通常用在数据量大、对数据实时性要求不高的场合,例如USB打印机、扫描仪、大容量存储设备、U盘等。

等时传输

等时传输同样可以传输大批量数据,但是对数据是否到达没有保证,它对实时性的要求很高,例如音频、视频等设备。


端点的数据结构

内核中,使用usb_host_endpoint来描述USB端点,这个结构体中包含了一个保存端点信息的结构体usb_endpoint_descriptor,驱动一般会关心其中保存的端点地址bEndpointAddress、端点类型bmAttributes、端点处理的最大字节数wMaxPacketSize、以及如果是中断类型端点的中断时间bInterval。

Nyqh8I.png

接口Interface

由上面的USB设备结构图我们可以看到,USB设备的端点包含在接口Interface中。USB接口用于每个USB接口仅控制着一种类型的USB连接,例如鼠标、键盘或者音频流。大多数的USB设备存在多个接口,因为每一个接口代表一个基础功能,因此每一个接口都需要一个驱动程序驱动。

USB接口在内核中使用usb_interface结构体描述,这个结构体一般由USB core传递给USB驱动,由USB驱动进行控制。比较重要的成员变量有:struct usb_host_interface *altsetting控制字段、unsigned num_altsetting控制数量、struct usb_host_interface *cur_altsetting指向控制选项的指针、int minor次设备号。

配置Configurations

由上面的USB设备结构图我们可以看到,USB设备的接口包含在配置Configurations中。 一个USB设备可以有多种配置,但是每一个时间点只能启用生效一个配置。

Linux内核中使用usb_host_config结构体描述USB设备的配置。一般来说驱动无需对配置进行读写操作。

USB驱动框架源码分析

​ 其实稍微阅读一下源码就会发现,USB驱动框架和之前研讨过的帧缓冲驱动框架非常相似。都是一个文件用来组装加载驱动框架的内核模块usb-skeleton.c(帧缓冲是fbmem.c),一个文件用来描述驱动框架相关的数据结构以及驱动注册方法等usb.h(帧缓冲是fb.h)。

​ 因此,先初步断定,Linux中的驱动框架都是一个套路,所以按照以往的经验,先从usb-skeleton.c这个驱动框架的模块入手分析。既然是Linux模块,当然要从入口处先分析了!下面审计模块初始函数usb_skel_init。

static int __init usb_skel_init(void)
{
   
	int result;

	/* register this driver with the USB subsystem */
    //
	result = usb_register(&skel_driver);
	if (result)
		err("usb_register failed. Error number %d", result);

	return result;
}

和猜想没错, 驱动模块加载必然是先注册驱动结构体,这个注册的驱动结构体usb_driver在模块中被初始化写好了name、probe探测函数、disconnect断开函数、id_table表(用来告诉内核该驱动支持的设备)。

static struct usb_driver skel_driver = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值