Linux系统下USB驱动程序的设计与开发
论文导读::操作系统是一个源码公开、结构清晰、功能强大。总线具有低成本、使用简单、支持即插即用、易于扩展等特点。本文首先介绍linux驱动程序的架构。
关键词:Linux,USB,驱动程序
0引言
Linux操作系统是一个源码公开、结构清晰、功能强大,且已成为一个稳定可靠功能完善的系统。其开发群体的有效组织和高效工作,使得linux系统稳定发展并得到良好维护。
USB总线是Intel、DEC、MicroSoft、IBM等公司联合提出的一种新的串行总线标准,主要用于PC机与外围设备的互联。USB总线具有低成本、使用简单、支持即插即用、易于扩展等特点,已被广泛地用在PC机及嵌入式系统上。
在已经研制的家庭网关中,CPU通过自带的USB接口控制USB设备。本文首先介绍linux驱动程序的架构发表论文,然后介绍USB总线,重点说明USB驱动程序的实现。
1.Linux驱动程序基础
设备驱动程序是操作系统内核和机器硬件之间的接口,为应用程序屏蔽了硬件的细节。应用程序看待硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它主要完成以下功能:对设备进行初始化,使设备投入运行和退出服务;把数据从内核传送到设备和从设备接受数据;以及检测和处理设备出现的错误等。
Linux系统的设备一般分为字符设备、块设备和网络设备三种。字符设备是指存取时没有缓存的设备。块设备的读写都有缓存来支持,并且块设备必须能够随机存取,字符设备则没有这个要求。一个文件系统要安装进入操作系统必须在块设备上。网络设备在Linux里做专门的处理。Linux的网络系统主要是基于BSD unix的socket机制。在系统和驱动程序之间定义有专门的数据结构(sk—buff)进行数据的传递。系统里支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持。
2.USB系统总线介绍
每一个USB设备会有一个或者多个的逻辑连接点,每个连接点叫端口。每个端口有4种数据传送方式:控制方式;等时方式;中断方式和大量方式。但是所有的端口0都是被用来传送配置和控制信息。
在主机和设备的端口之间的连接叫作管道,与端口0连接的一般称作为缺省管道。对于同样性质的一组端口的组合叫做接口发表论文,如果一个设备包含不止一个的接口就可以称之为复合设备。
同理,对于同样的类型的接口的组合可以称之为配置。但是每次只能有一个配置是可用的,而一旦该配置激活,里面的接口和端口就都同时可以使用。主机从设备发过来的描述符中来判断用的是哪个配置,哪个接口等等,而这些的描述字通常是在端口0中传送。
3.USB子系统
USB 是一种分层的总线结构,并且是由一个主机(host)来控制。主机用主/副协议来和外部USB设备通讯。USB上的通讯主要是两个方向进行的,一个是主机到设备的下行方向, 一个是设备到主机的上行方向,不支持设备间的直接通讯。依靠不同的设备类型,主要有4 种的传输方式::控制(control)、中断(interrupt)、同步(isochronous)、数据块(bulk);如果是从硬件开始来设计整个的系统,还要正确选择传输的方式。而作为一个驱动程序的书写者就只需要弄清楚他是采用的什么工作方式就行了。通常所有的传输方式下的主动权都在 host边。
在Linux系统中编写主机部分的USB驱动发表论文,我们不必了解太多的硬件知识,因为Linux 内核模块中提供了一块USB内核(USBcore),它给出专门的API来支持USB设备和主控制器。通过定义一系列数据结构,宏命令和函数对所有的硬件和设备支持部分进行抽象。
USB内核包含了所有USB设备驱动和主控制器驱动的共同的USB程序。这些函数主要集中在上层和底层API。如图1所示,有一个USB设备的驱动的API和一个主控制器的.驱动。
图1USB内核API层
4.USB设备驱动框架
USB设备驱动在内核模块中需要注册和注销。因此一个驱动必须注册2个入口点和一个设备节点。对于特别的USB设备(他们不适合在子系统中注册)一个驱动可以注册一对文件操作符和一个次设备号。一般一个驱动可以服务16个相似的USB设备。几乎所有的USB设备主设备号都是180。
4.1框架数据结构
所有的USB相关的函数和数据结构的名字都是以USB_开头的。下面给出在子系统中注册一个USB驱动程序的数据结构。
struct usb _driver {
const char *name; / /模块的名字
void* ( *probe)(struct usb_device *,unsigned int) ;/ /函数的进入指针
void ( *disconnect) ( struct usb_device *,void * ) ; / /撤销连接的函数进入指针
struct list_headdriver_list ;/ /给子系统内部使用,初始化时为 NULL
structfile_operations *fops ;/ /文件操作列表指针
int minor ;/ /次设备号
} ;
这里特别要提的就是文件操作的结构(structfile_operations),随着新功能不断加入 Linux内核,此文件操作的结构也变得越来越大,这种增长是不会有副作用的。因为对于特定的设备驱动,我们可以选择自己需要的函数,不需要的就设为NULL值就可以。下面主要列举一些USB常用的几个文件操作函数:
(1)int ( *open) ( struct inode *, struct file*) ; 设备打开操作一般是设备的第一个操作,不过有的设备可以不选择这个函数。那样设备的打开操作就会永远成功发表论文,但系统不会通知你的驱动程序。
(2) void ( *release)( struct inode * , struct file* ) ; 当节点关闭时调用这个操作。
(3) int ( *read) ( struct inode * , struct file * ,char * , int) ; 用来从设备中读取数据。函数返回一个非负值表示成功的读取了多时字节。
(4) int ( *write) ( struct inode * , struct file * ,const char * , int ) ; 向设备发数据。如果返回值非负,它就表示成功写入的字节数。
(5) int ( *select) (struct inode * , struct file * ,int , select_table * ) ; select一般用于程序询问设备是否可读或可写,或是否一个“异常”条件发生了。
(6) int ( *ioctl) ( struct inode * , struct file * ,unsigned int , unsigned long) ; 系统调用 ioctl 提供一种调用设备相关命令的方法。
(7) int ( *mmap) ( struct inode * , struct file* , struct vm_area _struct * ) ; 用来将设备内存映射到进程内存中。
(8) int ( *fsync) ( struct inode * , struct file* ) ; 刷新设备。
4.2框架进入指针
USB 驱动的框架增加了两个进入指针给普通的设备驱动。
(1) void * probe( struct usb_device * dev , unsigned int interface) ; 当一个新设备加入总线时,这个进入指针就被调用。然后设备驱动将创建一个新的设备数据结构实例。参数dev表示设备的上下文,他包含了所有USB描述符的地址。参数interface表示接口值。如果一个USB驱动想要绑定一个特别的设备或者接口,它必须返回一个指针。这个指针通常指向设备驱动的上下文结构。
(2) voiddisconnect ( struct usb_device * dev ,void * drv_context) ; 这个函数是在设备撤销连接时调用的。参数dev列出了设备上下文。撤销连接函数完成后,设备就脱离了USB的框架。以后USB驱动就不能再调用它了。
4.3框架函数
(1)int usb_register ( struct usb_driver * drv) ;这个函数是用来注册一个新的 USB 设备驱动。指针drv指向结构usb_driver。函数成功返回0。要不然返回一个错误值。
(2)voidusb_deregister ( struct usb_driver *drv) ; 此函数是注销 USB 设备驱动。
(3)voidusb_driver_claim_interface ( struct usb_driver * driver , struct usb_interface *iface ,void * drv_context) ; 此函数是在probe函数执行后,开始为设备驱动申请更多的接口。Drive指针指向一个完整的已经初始化的usb_driver结构。Iface 指向usb_interface结构,此结构是usb_config_descriptor(可以在usb_device结构中看到)的一部分(在probe函数中赋值)。Drv_context 指针主要指向设备驱动的上下文结构(看probe函数的返回值)。
(4)intusb_interface_claimed (struct usb_inter2face * iface); 这个函数是检查是否有其他驱动已经声明了这个接口。如果接口没有被其它驱动申请就返回0。
(5)voidusb_driver_release_interface(structusb_driver * driver , struct usb_interface * iface); 这个函数主要是来释放先前申请的接口。在 disconnect函数中, , 你不必释放任何在probe函数中申请的接口。
5.配置USB设备
USB内核API除了包括了一套选择或询问的描述符,还有一些配置和更换的设备函数。所有这些标准操作都是通过控制传输给设备的。
5.1数据结构的描述
Linux USB子系统通过扩展或内嵌标准的USB描述符来说明描述符的分级结构。这种结构有助于保存指向可选配置和接口的指针。只要被API调用,这些结构的元素就会被描述。关于描述符的详细信息可以在USB.H查到。
struct usb_device{
. . .
struct usb_config_descriptor* actconfig ;/ * the active configuration * /
. . .
struct usb_device_descriptordescriptor ;/ * Descriptor * /
struct usb_config_descriptor* config ; / * 所有的参数 * }
usb_device 结构是所有USB专门的描述符的根节点。在用驱动配置设备或者请求传输的时候发表论文,就必须分解描述符。
5.2标准的设备申请
为了查询或者设置一个特殊的配置或可选设置,可以用一个整型函数。并用这个函数建立标准的设备申请(指定设备的控制传输)。
(1)intusb_set_configuration (struct usb_device* dev , int configuration); 此函数是激活特殊的配置。0 < =configuration < dev - > descriptor .bNumConfigurations.
设configuration为0将设备设为无地址状态。这个意思是设备脱离这个设备地址并准备接受一个新的。一般不要设0。因为你将不能访问设备,直到被物理的重新连接到总线上。
(2) intusb_set_interface ( struct usb_device *dev , int interface , int alternate) ; 这个函数激活指定接口的可选设置。
(3) intusb_get_device_descriptor ( struct usb_device * dev) ; 这个函数取出了设备完整的描述符结构树。当一个设备连上总线时,这个函数就会自动被唤醒。或者当一个USB描述符改变时,此函数被调用。
(4) intusb_get_string ( struct usb_device *dev , unsigned short langid , unsigned charindex , void* buf , int size) ; 如果一个设备,配置或者接口描述符涉及到字符串索引值,这个函数可以用来重新获得字符描述符。标准的USB字符串是以UNICODE编码的。如果成功就返回0,要不然返回一个错误值。
6.结束语
USB的应用越来越广泛,传输速率越来越高。而Linux作为一种新的操作系统,其发展前景是无法估量的,同时也为USB总线与各种新型设备互连成为可能。在Linux下编写驱动程序的原理和思想与window环境下的驱动程序有很大的区别,在Linux环境下设计驱动程序发表论文,思想简洁,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便,还要考虑内核的前后兼容性,因此在设计和实现USB设备时应该注意这些问题。
参考文献:
[1]毛德操,胡希明.Linux内核源代码情景分析[M].杭州:浙江大学出版社,2003.
[2]Universal Serial Bus SpecificationRevision[Z]. Compaq, IBM, Intel, Microsoft, NEC, Northern Telecom, 1995.
[3]王伟,王自强,都思丹.USB设备上构建Linux系统的关键问题[J].电子测量技术,2008,(06).
[4]沈玉伟,杨永杰,房立鑫.基于μClinux嵌入式网络打印机服务器[J].计算机时代,2008,(05).
[5]吴丽丽.嵌入式平台下USB摄像头驱动的开发与加载[J].科技信息(学术研究),2008,(26).
[6]杜敏杰,马彦恒,刘利民.Linux下基于CY7C68013芯片的USB设备驱动程序开发[J].科学、技术与工程,2008,(21).
[7]卢志刚,刘建华,刘宝旭,许榕生.基于HID的USB监控技术的设计与实现[J].计算机工程,2010,(04).
[8]宋丽华,高珂.嵌入式Linux下USB摄像头驱动实现[J].计算机工程,2010,(09).
[9]孙永刚,张学勇,迟欢欢.基于Linux的USB设备驱动的实现[].信息技术,2010,(08).
[10]刘飞,张曦煌.基于嵌入式平台的USB摄像头驱动程序的实现[J].计算机工程与设计,2008,(08).
[11]肖珂,欧东梅,郭书军.嵌入式Linux下高速USB主控制器的设计与实现[J].现代电子技术,2009,(24).
[12]熊春杰.Linux内核移植与USB驱动开发[D].电子科技大学,2007.
[13]程科.嵌入式Linux设备驱动程序的设计与研究[D].电子科技大学,2007.
[14]王强东.面向嵌入式系统的多功能USB设备驱动研究[D].华中科技大学,2007.
【Linux系统下USB驱动程序的设计与开发】相关文章: