基于Linux的最小USB驱动程序框架设计

2012-07-25 03:19倪远平
微处理机 2012年3期
关键词:集线器驱动程序端点

方 骞,倪远平

(昆明理工大学,昆明650051)

1 引言

随着电脑软件和硬件的快速发展,传统的接口如串口、并口等通讯方式已经不能满足现有系统或者设备的数据传输需求。在这个背景下,以Intel为首的七家公司于1994年推出了USB(Universal Serial Bus)通用串行总线协议概念,主要是为了解决接口标准太多、传输速率偏低的弊端。每个USB设备都有专门的驱动程序来支持,研究所有USB驱动程序共同的部分,为快速开发不同USB设备的驱动程序提供了一个参考框架,节省了开发周期。

通过介绍Linux驱动程序的相关知识,以及对USB系统的深入理解,试图构造一个Linux下最小的USB驱动程序框架。

2 Linux驱动程序

在Linux内核中,任何设备都是以相对应的文件方式存在的,对设备的任何操作实际上都是通过对这个设备文件的操作完成的。读写设备文件就相当于操作设备的输入和输出。由于各个设备文件所对应的接口不同,设备驱动程序在Linux内核中就起着这样一个特殊的作用,它们像一个个黑盒子一样,使某个特定的硬件响应一个定义良好的内部编程接口,而这些接口完全隐藏了设备的工作细节,它们对用户来说是完全透明的,甚至感觉不到它们的存在。实际上,当用户进行操作时,内核将这种操作转换成一组标准化的调用再继续执行,而设备驱动程序的任务就是将这些调用映射到作用于实际硬件设备的特有操作上。

Linux系统设备有三种,一般分为字符设备、块设备和网络设备。字符设备是能够像字节流一样被访问的设备,没有缓存,对它的读写是以字节为单位的。块设备上的数据以块的形式存放,读写都有缓存的支持,而且能够随机存取。网络设备同时具有字符设备和块设备的部分特点,它的输入和输出是有结构的,但数据的大小却是不固定的。网络设备在Linux里有一系列专门的处理方式,这里就不再详细介绍。

3 USB基础

3.1 USB的硬件结构

USB(Universal Serial Bus)即“通用串行外部总线”,是主机和外围设备之间的一种连接。USB采用四线电缆,其中两根是用来传送数据的串行通道,另外两根为下游的设备提供电源。

USB是基于令牌的总线。USB主机控制器广播令牌,总线上设备检测令牌中的地址是否与自身相符,通过接收或发送数据给主机来响应。USB系统采用级联星型拓扑,该拓扑由三个基本部分组成:主机(Host)、集线器(Hub)和功能设备。USB主机控制器通过根集线器与其他USB设备相连。集线器也属于USB设备,通过它可以在一个USB接口上扩展出多个接口。除根集线器外,最多可以层叠5个集线器。一条USB总线上可以外接127个设备,包括根集线器和其他集线器。图1为USB总线的连接方式。

图1 USB总线的连接方式

3.2 USB的软件架构

每个USB只有一个主机,它包括USB总线接口和USB系统。USB总线接口处理电气层与协议层互连。USB系统用主控制器管理主机与USB设备间的数据传输,它与主控制器间的接口依赖于主控制器的硬件定义。同时,USB系统也负责管理USB资源,这使客户访问USB成为可能。

USB客户软件位于软件结构的最高层,负责处理特定USB设备驱动器。客户程序层描述所有直接作用于设备的软件入口。当设备被系统检测到后,这些客户程序将直接作用于外围硬件。这个共享的特性将USB系统软件置于客户及其设备之间,由客户程序对USB驱动程序在客户端形成的设备映像进行处理。

3.3 USB的数据流传输

端点是USB设备中的实际物理单元,USB数据传输就是在主机和USB设备各个端点之间进行的。USB端点有四种不同的类型,控制、中断、批量和等时。控制和批量端点用于异步的数据传输,而中断和等时端点是周期性的。USB端点只能往一个方向传送数据,可以看作是单向管道,它被捆绑为接口,而USB接口只处理一种USB逻辑连接。USB接口本身又被捆绑为配置,一个USB设备可以有多个配置,而且可以在配置之间切换以改变设备的状态。

4 Linux系统最小USB驱动程序框架实现

每个USB设备都会有一个相应的驱动程序,结合Linux内核源代码,将讨论所有USB设备所共通的部分,在这里并不列出全部代码,而是将其中核心部分列出加以讨论。

要实现一个USB的驱动程序,首先要构造一个内核模块,这个模块定义了两个函数,其中一个在模块被装载到内核时调用,而另一个则在模块被移除时调用。此时,这个简单的模块还不是驱动程序,需要在这两个函数内加入注册和注销USB设备的函数才能成为一个驱动程序模块。注册函数在USB驱动程序加载时被调用,注销函数在卸载时被调用。

demo_driver是一个usb_driver类型的结构体,这个结构体包括许多回调函数和变量,它们向USB核心代码描述了USB驱动程序。以下是这个结构体的主要成员:

THIS_MODULE是指向该驱动程序模块所有者的指针,USB核心使用它来正确地对该USB驱动程序进行引用计数,使它不会在不合适的时刻被卸载掉。demo是指向驱动程序名字的指针,在内核的所有USB驱动程序中它必须是唯一的,通常被设置为和驱动程序模块相同的名字。

demo_table是指向struct usb_device_id表的指针。如果没有设置该变量,USB驱动程序中的探测回调函数不会被调用。

MODULE_DEVICE_TABLE(usb,demo_table);

USB_DEMO_INFO_ID代表的是USB设备的主次设备号,在demo_table中包含很多条这样的设备信息。只要其中包含所要连接的USB设备信息,主机就能识别这个设备。写新的USB设备驱动时,也只需将新设备的主次设备号加入这个表中,就能被主机识别。

demo_probe和demo_disconnect是指向USB驱动程序中探测函数和断开函数的指针。当USB核心认为它有一个struct usb_interface可以由该驱动程序处理时,它将调用探测函数。

当struct usb_interface被从系统中移除或者驱动程序正在从USB核心中卸载时,USB核心将调用断开函数。

demo_class是探测函数和断开函数中注册某个设备或注销某个设备时所调用的函数需要的参数,它是一个指向usb_class_driver结构的指针,定义许多不同的参数,在注册一个设备号时USB驱动程序需要USB核心知道这些参数。

demo是用来描述设备的名字。USB_DEMO_MINOR_BASE是为该驱动程序指派的次设备号范围的开始值。与该驱动程序相关联的所有设备都是唯一的,以该值开始递增的次设备号来创建的。demo_fops是指向struct file_operations的指针,驱动程序定义该结构体,用它来注册为字符设备,其中包含了一组函数指针。每个打开的文件和一组函数关联。这些操作主要用来实现系统调用,这里简单定义了open、release、read、write这几个最基本的函数。

现在,我们只需定义这几个空函数,就可以实现一个最小的USB驱动程序的框架。

5 结束语

随着USB接口的广泛应用,对于USB驱动程序的研究显得尤为重要。USB驱动程序框架,实现的是USB设备不同应用程序之外所共有的部分,只要在程序中加入不同设备的信息,就能够完成对不同设备的识别。如果要实现USB设备的不同功能,仅需要修改驱动程序中demo_fops结构体中的操作函数就能够完成。试验证明,上面设计的程序运行良好,通用性很高,具有很强的可移植性。

[1] [美]Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman,著.Linux设备驱动程序[M].魏永明,耿岳,钟书毅,译.北京:中国电力出版社,2005.

[2] 韦东山.嵌入式Linux应用开发完全手册[M].北京:人民邮电出版社,2010.

[3] 毛德操,胡希明.Linux内核源代码情景分析[M].杭州:浙江大学出版社,2003.

猜你喜欢
集线器驱动程序端点
非特征端点条件下PM函数的迭代根
基于差分QPSO的多能源集线器系统优化调度
基于可变编程集线器的整车线束模块化设计
音乐聆赏新世代 Bowers & Wilkins Formation Audio无线音乐集线器
不等式求解过程中端点的确定
阻止Windows Update更新驱动程序
计算机硬件设备驱动程序分析
基丁能虽匹配延拓法LMD端点效应处理
妙用鼠标驱动
驱动程序更新与推荐