linux下linux usb驱动开发程序开发有哪些背景及其意义

Linux系统下linux usb驱动开发程序的设计与开發

  论文导读::是一个源码公开、结构清晰、功能强大总线具有低成本、使用简单、支持即插即用、易于扩展等特点。本文首先介绍linux驅动程序的架构

  关键词:Linux,USB驱动程序

  Linux操作系统是一个源码公开、结构清晰、功能强大,且已成为一个稳定可靠功能完善的系統其开发群体的有效组织和高效工作,使得linux系统稳定发展并得到良好维护

  USB总线是Intel、DEC、MicroSoft、IBM等公司联合提出的一种新的串行总线标准,主要用于PC机与外围设备的互联USB总线具有低成本、使用简单、支持即插即用、易于扩展等特点,已被广泛地用在PC机及嵌入式系统上

  在已经研制的家庭网关中,CPU通过自带的USB接口控制USB设备本文首先介绍linux驱动程序的架构发表论文,然后介绍USB总线重点说明linux usb驱动开发程序嘚实现。

  1.Linux驱动程序基础

  设备驱动程序是操作系统内核和机器硬件之间的接口为应用程序屏蔽了硬件的细节。应用程序看待硬件設备只是一个设备文件应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分它主要完成以下功能:對设备进行初始化,使设备投入运行和退出服务;把数据从内核传送到设备和从设备接受数据;以及检测和处理设备出现的错误等

  Linux系统的设备一般分为字符设备、块设备和网络设备三种。字符设备是指存取时没有缓存的设备块设备的读写都有缓存来支持,并且块设備必须能够随机存取字符设备则没有这个要求。一个文件系统要安装进入操作系统必须在块设备上网络设备在Linux里做专门的处理。Linux的网絡系统主要是基于BSD unix的socket机制在系统和驱动程序之间定义有专门的数据结构(sk―buff)进行数据的传递。系统里支持对发送数据和接收数据的缓存提供流量控制机制,提供对多协议的支持

  2.USB系统总线介绍

  每一个USB设备会有一个或者多个的逻辑连接点,每个连接点叫端口烸个端口有4种数据传送方式:控制方式;等时方式;中断方式和大量方式。但是所有的端口0都是被用来传送配置和控制信息

  在主机囷设备的端口之间的连接叫作管道,与端口0连接的一般称作为缺省管道对于同样性质的一组端口的组合叫做接口发表论文,如果一个设備包含不止一个的接口就可以称之为复合设备

  同理,对于同样的类型的接口的组合可以称之为配置但是每次只能有一个配置是可鼡的,而一旦该配置激活里面的接口和端口就都同时可以使用。主机从设备发过来的描述符中来判断用的是哪个配置哪个接口等等,洏这些的描述字通常是在端口0中传送

  USB 是一种分层的总线结构,并且是由一个主机(host)来控制主机用主/副协议来和外部USB设备通讯。USB上嘚'通讯主要是两个方向进行的一个是主机到设备的下行方向, 一个是设备到主机的上行方向不支持设备间的直接通讯。依靠不同的设備类型主要有4 种的传输方式::控制(control)、中断(interrupt)、同步(isochronous)、数据块(bulk);如果是从硬件开始来设计整个的系统,还要正确选择传输的方式而作为一个驱动程序的书写者就只需要弄清楚他是采用的什么工作方式就行了。通常所有的传输方式下的主动权都在 host边

  在Linux系统中編写主机部分的linux usb驱动开发发表论文,我们不必了解太多的硬件知识因为Linux 内核模块中提供了一块USB内核(USBcore),它给出专门的API来支持USB设备和主控制器通过定义一系列数据结构,宏命令和函数对所有的硬件和设备支持部分进行抽象

  USB内核包含了所有USB设备驱动和主控制器驱动嘚共同的USB程序。这些函数主要集中在上层和底层API如图1所示,有一个USB设备的驱动的API和一个主控制器的驱动

  4.USB设备驱动框架

  USB设备驱動在内核模块中需要注册和注销。因此一个驱动必须注册2个入口点和一个设备节点对于特别的USB设备(他们不适合在子系统中注册)一个驅动可以注册一对文件操作符和一个次设备号。一般一个驱动可以服务16个相似的USB设备几乎所有的USB设备主设备号都是180。

  4.1框架数据结构

  所有的USB相关的函数和数据结构的名字都是以USB_开头的下面给出在子系统中注册一个linux usb驱动开发程序的数据结构。

  这里特别要提的就昰文件操作的结构(structfile_operations)随着新功能不断加入 Linux内核,此文件操作的结构也变得越来越大这种增长是不会有副作用的。因为对于特定的设備驱动我们可以选择自己需要的函数,不需要的就设为NULL值就可以下面主要列举一些USB常用的几个文件操作函数:

  (1)int ( *open) ( struct inode *, struct file*) ; 设备打开操作一般昰设备的第一个操作,不过有的设备可以不选择这个函数那样设备的打开操作就会永远成功发表论文,但系统不会通知你的驱动程序

  4.2框架进入指针

  USB 驱动的框架增加了两个进入指针给普通的设备驱动。

当一个新设备加入总线时这个进入指针就被调用。然后设备驅动将创建一个新的设备数据结构实例参数dev表示设备的上下文,他包含了所有USB描述符的地址参数interface表示接口值。如果一个linux usb驱动开发想要綁定一个特别的设备或者接口它必须返回一个指针。这个指针通常指向设备驱动的上下文结构

  5.配置USB设备

  USB内核API除了包括了一套選择或询问的描述符,还有一些配置和更换的设备函数所有这些标准操作都是通过控制传输给设备的。

  5.1数据结构的描述

  Linux USB子系统通过扩展或内嵌标准的USB描述符来说明描述符的分级结构这种结构有助于保存指向可选配置和接口的指针。只要被API调用这些结构的元素僦会被描述。关于描述符的详细信息可以在USB.H查到

  usb_device 结构是所有USB专门的描述符的根节点。在用驱动配置设备或者请求传输的时候发表论攵就必须分解描述符。

  5.2标准的设备申请

  为了查询或者设置一个特殊的配置或可选设置可以用一个整型函数。并用这个函数建竝标准的设备申请(指定设备的控制传输)

  设configuration为0将设备设为无地址状态。这个意思是设备脱离这个设备地址并准备接受一个新的┅般不要设0。因为你将不能访问设备直到被物理的重新连接到总线上。

  (3) intusb_get_device_descriptor ( struct usb_device * dev) ; 这个函数取出了设备完整的描述符结构树当一个设备連上总线时,这个函数就会自动被唤醒或者当一个USB描述符改变时,此函数被调用

如果一个设备,配置或者接口描述符涉及到字符串索引值这个函数可以用来重新获得字符描述符。标准的USB字符串是以UNICODE编码的如果成功就返回0,要不然返回一个错误值

  USB的应用越来越廣泛,传输速率越来越高而Linux作为一种新的操作系统,其发展前景是无法估量的同时也为USB总线与各种新型设备互连成为可能。在Linux下编写驅动程序的原理和思想与window环境下的驱动程序有很大的区别在Linux环境下设计驱动程序发表论文,思想简洁功能也很强大,但是支持函数少只能依赖kernel中的函数,有些常用的操作要自己来编写而且调试也不方便,还要考虑内核的前后兼容性因此在设计和实现USB设备时应该注意这些问题。

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

  [4]沈玉伟,杨永杰,房立鑫.基于μClinux嵌入式网络打印机服务器[J].计算机時代,2008,(05).

  [5]吴丽丽.嵌入式平台下USB摄像头驱动的开发与加载[J].科技信息(学术研究),2008,(26).

  [7]卢志刚,刘建华,刘宝旭,许榕生.基于HID的USB监控技术的设计与实现[J].计算机工程,2010,(04).

  [10]刘飞,张曦煌.基于嵌入式平台的USB摄像头驱动程序的实现[J].计算机工程与设计,2008,(08).

  [11]肖珂,欧东梅,郭书军.嵌入式Linux下高速USB主控制器的设计與实现[J].现代电子技术,2009,(24).

  [13]程科.嵌入式Linux设备驱动程序的设计与研究[D].电子科技大学,2007.

  [14]王强东.面向嵌入式系统的多功能USB设备驱动研究[D].华中科技夶学,2007.

【Linux系统下linux usb驱动开发程序的设计与开发】相关文章:

 初次接触与OS相关的设备驱动编写感觉还挺有意思的,为了不至于忘掉看过的东西笔记跟总结当然不可缺,更何况我决定为嵌入式卖命了好,言归正传我说一说这段时间的收获,跟大家分享一下Linux的驱动开发但这次只先针对Linux的USB子系统作分析,因为周五研讨老板催货当然,还会顺带提一下其他的驱動程序写法
事实上,Linux的设备驱动都遵循一个惯例——表征驱动程序(用driver更贴切一些应该称为驱动器比较好吧)的结构体,结构体里面應该包含了驱动程序所需要的所有资源用术语来说,就是这个驱动器对象所拥有的属性及成员由于Linux的内核用c来编写,所以我们也按照這种结构化的思想来分析代码但我还是希望从OO的角度来阐述这些细节。这个结构体的名字有驱动开发人员决定比如说,鼠标可能有一個叫做mouse_dev的struct键盘可能由一个keyboard_dev的struct(dev 这里我们得补充说明一下一些USB的协议规范细节。USB能够自动监测设备并调用相应得驱动程序处理设备,所鉯其规范实际上是相当复杂的幸好,我们不必理会大部分细节问题因为Linux已经提供相应的解决方案。就我现在的理解来说USB的驱动分为兩块,一块是USB的bus驱动这个东西,Linux内核已经做好了我们可以不管,但我们至少要了解他的功能形象得说,USB的bus驱动相当于铺出一条路来让所有的信息都可以通过这条USB通道到达该到的地方,这部分工作由usb_core来完成当USB设备接到USB控制器接口时,usb_core就检测该设备的一些信息例如苼产厂商ID和产品的ID,或者是设备所属的class、subclass跟protocol以便确定应该调用哪一个驱动处理该设备。里面复杂细节我们不用管我们要做的是另一块笁作——usb的设备驱动。也就是说我们就等着usb_core告诉我们要工作了,我们才工作
       从开发人员的角度看,每一个usb设备有若干个配置(configuration)组成每個配置又可以有多个接口(interface),每个接口又有多个设置(setting图中没有给出)而接口本身可能没有端点或者多个端点(end point)。USB的数据交换通过端点来进荇主机与各个端点之间建立起单向的管道来传输数据。而这些接口可以分为四类:

在逻辑上一个USB设备的功能划分是通过接口来完成的。比如说一个USB扬声器可能会包括有两个接口:一个用于键盘控制,另外一个用于音频流传输而事实上,这种设备需要用到不同的两个驅动程序来操作一个控制键盘,一个控制音频流但也有例外,比如蓝牙设备要求有两个接口,第一用于ACL跟EVENT的传输另外一个用于SCO链蕗,但两者通过一个驱动控制在Linux上,接口使用struct MODULE_DEVICE_TABLE的第一个参数是设备的类型如果是USB设备,那自然是usb(如果是PCI设备那将是pci,这两个子系統用同一个宏来注册所支持的设备这涉及PCI设备的驱动了,在此先不深究)后面一个参数是设备表,这个设备表的最后一个元素是空的用于标识结束。代码定义了USB_SKEL_VENDOR_ID是0xfff0USB_SKEL_PRODUCT_ID是0xfff0,也就是说当有一个设备接到集线器时,usb子系统就会检查这个设备的vendor 得到了该usb_device之后我们要对我们洎定义的usb_skel各个状态跟资源作初始化。这部分工作的任务主要是向usb_skel注册该usb设备的端点这里可能要补充以下一些关于usb_interface_descriptor的知识,但因为内核源碼对该结构体的注释不多所以只能靠个人猜测。在一个usb_host_interface结构里面有一个usb_interface_descriptor叫做desc的成员他应该是用于描述该interface的一些属性,其中bNumEndpoints是一个8位(b

接下来的工作是向系统注册一些以后会用的的信息首先我们来说明一下usb_set_intfdata(),他向内核注册一个data这个data的结构可以是任意的,这段程序向内核注册了一个usb_skel结构就是我们刚刚看到的被初始化的那个,这个data可以在以后用usb_get_intfdata来得到usb_set_intfdata(interface, 真正完成对设备IO操作的函数。所以他的核心内容应該是skel_fops这里补充一些我个人的估计:因为usb设备可以有多个interface,每个interface所定义的IO操作可能不一样所以向系统注册的usb_class_driver要求注册到某一个interface,而不是device因此,usb_register_dev的第一个参数才是interface而第二个参数就是某一个usb_class_driver。通常情况下linux系统用主设备号来识别某类设备的驱动程序,用次设备号管理识别具体的设备驱动程序可以依照次设备号来区分不同的设备,所以这里的次设备好其实是用来管理不同的interface的,但由于这个范例只有一个interface在代码上无法求证这个猜想。 到目前为止我们已经分析完usb子系统要求的各个主要操作,下一部分我们在讨论一下对USB设备的IO操作Linux linux usb驱动開发框架分析(六)    说到usb子系统的IO操作,不得不说usb request block简称urb。事实上可以打一个这样的比喻,usb总线就像一条高速公路货物、人流之类的鈳以看成是系统与设备交互的数据,而urb就可以看成是汽车在一开始对USB规范细节的介绍,我们就说过USB的endpoint有4种不同类型也就是说能在这条高速公路上流动的数据就有四种。但是这对汽车是没有要求的所以urb可以运载四种数据,不过你要先告诉司机你要运什么目的地是什么。我们现在就看看struct   urb所发送的目标设备 unsigned int pipe     一个管道号码,该管道记录了目标设备的端点以及管道的类型每个管道只有一种类型和一个方向,它与他的目标设备的端点相对应我们可以通过以下几个函数来获得管道号并设置管道类型:   当一个urb把数据送到设备时,这个urb会由系统返回给驱动程序并调用驱动程序的urb完成回调函数处理。这时status记录了这次数据传输的有关状态,例如传送成功与否成功的话会是0。     要能够运货当然首先要有车所以第一步当然要创建urb:     struct urb 当我们的卡车运货之后,系统会把它调回来并调用urb完成回调函数,并把这辆车作为函数传递给驱动程序我们应该在回调函数里面检查status字段,以确定数据的成功传输与否下面是用urb来传送数据的细节。 /* initialize the urb properly */ usb_fill_bulk_urb(urb, request是控制消息的USB请求徝、requesttype是控制消息的USB请求类型value是控制消息的USB消息值,index是控制消息的USB消息索引具体是什么,暂时不是很清楚希望大家提供说明。     至此Linux丅的linux usb驱动开发框架分析基本完成了。

我要回帖

更多关于 linux usb驱动开发 的文章

 

随机推荐