USB设备驱动程序

2024-07-29

USB设备驱动程序(精选八篇)

USB设备驱动程序 篇1

USB端口已经成为便携式PC和平板电脑的标准配置,USB设备在为用户带来便利和快捷的同时也逐步成为了“用电大户”,直接影响着主机的续航时间和电池寿命。所以为USB设备编写的驱动程序应该采取积极的电源管理策略,及时地切换设备运行状态,以便有效地降低功耗。

1 主要技术介绍

1.1 WDF介绍

WDF(Windows Driver Foundation)是在WDM(Windows Driver Model)的基础上发展而来的新一代驱动程序模型。它提供了内核模式驱动程序框架(KMDF)和用户模式驱动程序框架(UMDF)两种模式[1],实现了完全集成的即插即用和电源管理模型。驱动程序框架管理着与操作系统内核相关的通信,通过隔离驱动程序与系统内核,降低了驱动程序对内核的影响,提高了系统稳定性[2]。

1.2 内核模式驱动程序框架

内核模式驱动程序框架KMDF是随Windows驱动程序工具包WDK(Windows Driver Kit)一同被发行[3],为驱动程序提供基于对象的接口和内核模式驱动程序所需的基本功能。默认操作仅需少量的通用代码,剩下的大部分工作由框架内定义的对象及方法来实现,保证用户开发出的驱动程序与每个后续的Windows版本兼容[4]。该框架具有以下优点:

• 提供了比WDM更容易使用的驱动程序接口。

• 可处理WDM驱动程序需要人工处理的许多操作。

• 提供了支持多处理器环境所需的大部分同步代码。

1.3 选择性挂起

当计算机处于S0状态(全部硬件设备打开或正常工作)时,为了降低功耗,在不影响计算机工作状态的前提下将长时间处于“空闲”状态的USB设备切换至“睡眠”状态,并在必要时刻重新将其唤醒,这种工作机制被称为USB设备的“选择性挂起”。一个USB设备进入“睡眠”状态,不会影响连接到同一个USB集线器上的其它设备[5],其功耗状态可以用Dx表示,x取值0到3,数字越大表示功耗越小[6]。具体说明如下:

• D0:设备已开启并处于工作状态,以系统允许的最大功耗及最高性能运行。

• D1/D2:设备处于中度睡眠状态,设备已经被使用,但以较低的性能运行。

• D3:设备处于深度睡眠状态,设备仅保证唤醒所需的最小供电。

1.4 设备栈与电源策略所有者

一个物理设备的驱动任务通常由几个驱动程序共同完成。每个驱动程序对应一个设备对象,它们按层布局,组成一个设备栈。

电源策略所有者PPO(Power Policy Owner)是指在设备栈中能够管理设备的电源策略、控制设备功耗状态并向设备栈发送请求的那个驱动程序。在每个设备栈中只能有一个驱动程序作为PPO,虽然栈中的任何驱动程序都可以充当PPO,但通常由USB设备的KMDF功能驱动程序来完成这个任务。电源策略所有者负责启用和禁用以下功能:

• 设备自身处于“空闲”状态但系统保持S0状态时,设备进入“睡眠”状态。

• 设备在检测到外部事件时从“睡眠”状态自行唤醒。

• 设备在检测到外部事件时将整个系统从“睡眠”状态唤醒。

2 I/O队列

2.1 电源管理队列与非电源管理队列

基于KMDF框架的驱动程序通常是与框架通信,而不是直接与操作系统的内核组件,所有的读、写和设备I/O控制请求必须由队列对象处理。该队列对象从系统接收请求然后分发给驱动程序的回调函数,它可以支持电源管理特性,也可以不支持此特性。

当一个请求到达电源管理队列,KMDF框架确保将其分发至驱动程序之前设备处于D0状态。也就是说,当设备离开其工作状态(D0)时,电源管理的队列对象对请求进行排队,但是不会将请求分发给驱动程序,在设备重新进入D0之前一直等待。非电源管理的队列对象会无视设备状态而继续分发请求[7]。一般情况下,一个驱动程序设置一个非电源管理队列接收I/O设备的控制请求,同时设置一个或多个电源管理队列接收读、写和其它与功耗相关的请求。对于KMDF驱动程序,若要将一个队列对象配置为电源管理队列通常是在EvtDriverDeviceAdd回调例程中完成。

2.2 PPO在电源管理队列中的作用

电源管理队列处理传入“睡眠”设备请求的方式取决于驱动程序是否是设备栈的PPO。对于处在“睡眠”状态的设备,PPO的电源管理队列支持“上电逻辑”。当I/O请求到达时,队列的“上电逻辑”可以将设备切换到D0状态,然后向驱动程序分发请求,且不需任何特殊代码。非PPO的电源管理队列不支持“上电逻辑”,当I/O请求到达时,队列对象将请求排队,但是不启动唤醒过程。具体过程如图1所示。

2.3 电源管理队列的使用条件

电源管理队列为驱动程序的开发提供了便利,但对它的使用不是无条件的。在设备栈中,如果一个KMDF驱动程序处于PPO之上,则无法使用电源管理队列。因为在设备被挂起时,设备功耗已经被降为Dx,但系统仍然处于S0并且可以向设备发送I/O请求。框架却不会从电源管理队列提交请求,致使I/O请求将阻塞设备栈。例如,驱动程序A和驱动程序B组成一个简单的设备栈,驱动程序B是PPO。假设场景1中的驱动程序A使用非电源管理队列,场景2中的驱动程序A使用电源管理队列,设备最初都处于“睡眠”状态,通过图2比较两者的不同。

在场景1中,系统发送一个I/O请求,驱动程序A通过非电源管理的队列对象收到了这个请求。经过处理之后,向下传送。B的队列接收请求后唤醒设备,并将请求分发给驱动程序B,请求被迅速处理。

在场景2中,系统发送一个I/O请求,驱动程序A的电源管理队列接收到请求。因为驱动程序A不是PPO,不能唤醒设备。队列对象将挂起请求,整个设备栈则进入“死锁”状态。

3 选择性挂起的工作机制

在实现USB设备挂起与恢复的操作中,KMDF框架处理所有与底层驱动程序通信相关的工作,同时监视着每个设备对象的电源管理队列的所有I/O活动。

一个空闲计时器记录着设备处于“空闲”状态时间,默认的超时时间为5秒。如果直至“空闲计时器”超时,都没有任何I/O请求到达设备对象的电源管理队列,KMDF框架将发送控制请求,在I/O队列中的所有I/O请求被响应后,调用回调函数将设备从D0切换到Dx状态。对于不支持电源管理的队列对象,需要框架在驱动程序的EvtDeviceD0Exit回调函数中显性调用WdfIoTargetStop方法把设备切换到“睡眠”状态。设备被挂起后,框架在下列情况下将向设备栈发送“上电”请求,并调用驱动程序的回调函数来唤醒设备:

• 一个I/O请求到达驱动程序的电源管理队列。

• 用户通过设备管理器关闭USB选择性挂起。

• 驱动程序调用WdfStopIdle方法。

4 实现选择性挂起

KMDF功能驱动程序使用WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS结构来保存“挂起”策略的各种设置参数,结构的成员变量如下:

• IdleTimeout:表示空闲计时器的超时时间。如果设置为IdleTimeoutDefaultValue,则时间为5000毫秒。

• UserControlOfIdleSettings:设置为IdleAllowUserControl表示赋予用户更改设备“挂起”设置的权限。相反,IdleDoNotAllowUserControl表示禁止用户更改。

• Enabled:设置为WdfUseDefault,表示启用对选择性挂起的支持。

• DxState:表示被框架挂起设备的功耗状态。需要将其设置为PowerDeviceMaximum,以保证框架能够根据设备性能自动匹配正确的参数。

4.1 启用选择性挂起

驱动程序在EvtDriverDeviceAdd回调函数中,通过WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT方法完成对WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS结构的初始化工作,然后调用WdfDeviceAssignS0IdleSettings方法将设置的参数传送给框架。以下面的代码片段为例:

WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;

WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend);

idleSettings.IdleTimeout = 25000;

WdfDeviceAssignS0IdleSettings(Device, &idleSettings);

在上例中,WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT方法有2个参数:一个是指向WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS结构的指针,另一个是为了支持选择性挂起而将枚举型变量设置为IdleUsbSelectiveSuspend。空闲计时器的超时时间被设置为25秒,同时DxState和UserControlOfIdleSettings参数使用框架的缺省值。然后,框架调用WdfDeviceAssignS0IdleSettings方法来启用“挂起”支持,并向框架注册各种参数设定。代码被执行后,当设备空闲时,框架将其切换到D3状态。如果要改变“挂起”策略的设置参数,只需重新进行参数初始化并再次调用WdfDeviceAssignS0IdleSettings方法即可。

4.2 阻止USB设备挂起

当系统处于S0状态,如果一个USB设备句柄正在被使用或设备正在充电,即使空闲超时,该设备也不允许被切换至“睡眠”状态。驱动程序通过调用WdfDeviceStopIdle方法阻止框架挂起一个空闲设备。如果空闲计时器没有超时,并且设备处于D0状态,框架将关闭空闲计时器。如果设备已经处于Dx状态,框架将把设备切换D0状态。当设备允许被挂起时,驱动程序通过调用WdfDeviceResumeIdle方法重启空闲计时器。

5 远程唤醒

KMDF框架可以向一个处于“睡眠”状态的USB设备发出唤醒信号,将其从低功耗状态切换至工作状态。如果系统处于工作状态S0,那么这个过程叫做“从S0唤醒”,如果系统处于睡眠状态(S1~S4),则叫做“从Sx唤醒”,它们统称“远程唤醒”。用户不需要编写任何代码就可以实现从S0唤醒,因为KMDF框架对其提供了很好的支持。然而,如果系统处于Sx状态,需要手工编写代码来实现远程唤醒。

5.1 查看设备信息

WDF_USB_DEVICE_INFORMATION结构中保存着设备硬件的特征信息,通过对其成员变量Traits进行识别可以判断设备是否支持远程唤醒。以下面的代码片段为例:

WDF_USB_DEVICE_INFORMATION deviceInfo;

WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo);

status = WdfUsbTargetDeviceRetrieveInformation(pDeviceContext->UsbDevice,&deviceInfo);

waitWakeEnable = deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;

在上例中,WDF_USB_DEVICE_INFORMATION_INIT方法完成对WDF_USB_DEVICE_INFORMATION结构的初始化工作,WdfUsbTargetDeviceRetrieveInformation方法通过设备对象的句柄将设备的硬件信息保存至结构变量中。如果变量waitWakeEnable的值为true则说明设备支持远程唤醒,否则为不支持。

5.2 启用远程唤醒

KMDF功能驱动程序只需完成“唤醒”设置的初始化工作,KMDF框架和底层的USB总线驱动程序负责发送请求并将设备切换回“工作”状态。“唤醒”设置的各种参数保存在WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS结构中,其主要成员变量设置如下:

• Enabled:设置为WdfUseDefault。

• DxState:设置为PowerDeviceMaximum。

• UserControlOfWakeSettings:设置为WakeAllowUserControl。

下例说明如何初始化唤醒设置并启用远程唤醒:

WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;

WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);

status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);

WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT方法来完成结构变量的初始化工作,所有参数均使用缺省值。WdfDeviceAssignSxWakeSettings方法负责将设置的参数传送给KMDF框架。如果操作成功,处于Dx状态的设备将被唤醒。

6 结 语

作为全新的驱动程序框架,KMDF在内核模式下为开发者提供了一个面向对象、基于事件驱动的开发平台,极大地简化了USB设备的功耗控制工作。文中介绍了选择性挂起相关技术、说明了I/O请求在不同类型设备栈中的分发流程、展示了KMDF框架下实现选择性挂起的步骤和相关函数指令。

参考文献

[1]李正平,徐超.WDF设备驱动程序的设计与实现[J].计算机技术与发展,2007,17(5):228-229.

[2]邹敬轩,蔡皖东.基于WDF过滤驱动的USB存储设备监控系统[J].计算机工程与科学,2010,32(3):42-43.

[3]胡晓力,田有先.KMDF框架研究与温室监控驱动开发[J].农机化研究,2008(6):177-178.

[4]Orwick P,Smith G.Developing Drivers with the Windows?Driver Foundation[M].Washington:Microsoft Press,2007:10-11.

[5]Microsoft Corporation.Selective Suspend in USB Drivers[M].Wash-ington:Microsoft Press,2009:4.

[6]Axelson J.USB Complete-The Developers Guide4th Edition[M].Mad-ison:Lakeview Research LLC,2009:399-407.

轻松掌控USB设备 篇2

优盘装不了大容量文件

将保存在计算机系统中的文件,拷贝到优盘之类的USB设备中,可以说操作很简单,只要用鼠标将目标文件从计算机硬盘中拖放到优盘中即可。可是,最近小张却遇到难题了,他想用优盘到同事的计算机中复制一个3GB左右的高清电影时,却怎么操作都不成功。同事说他的优盘可能使用了不合适的分区格式,必须使用NTFS分区格式,才能支持2GB以上大小的文件传输。小张认为这不是多大难事,恰好自己的优盘没有保存重要数据,直接使用NTFS分区格式对优盘进行格式化,不就解决问题了嘛!

想到做到,小张立即将优盘插入到同事的Vista系统中,双击系统桌面上的“计算机”图标,用鼠标右键单击其后界面中的优盘分区图标,选择右键菜单中的“属性”命令,切换到优盘设备属性对话框,点击“常规”标签,在对应标签页面中发现优盘当前的分区格式真的是FAT32文件系统。返回优盘的右键菜单,执行“格式化”命令后,看到格式化对话框的“文件系统”位置处,只有FAT、FAT32这两种分区格式,而没有自己熟悉的NTFS分区格式。那怎样才能将优盘格式化成NTFS分区格式,从而成功复制大容量文件呢?

几番尝试后,小张一脸茫然,不知道如何是好。毫无头绪之际,用手机将笔者呼了过来。经过一阵摸索,笔者很轻松地解决了问题,下面就是具体解决问题的步骤:

首先进入Vista系统的计算机窗口,找到优盘分区图标,并用鼠标右键单击该图标,执行右键菜单中的“属性”命令,进入优盘设备的属性对话框,点击“硬件”标签,切换到如图1所示的标签设置页面。

其次在“所有磁盘驱动器”列表中,选中与目标优盘设备相对应的名称,按下“属性”按钮,展开优盘硬件属性设置框,选择“策略”标签,展开策略标签设置页面,检查这里的“为提高性能而优化”选项是否处于选中状态,如果发现其没有被选中时,应该及时重新选中它,再单击“确定”按钮保存设置操作。

接着重新启动Vista系统,再次进入计算机窗口,用鼠标右键单击目标优盘分区图标,执行“格式化”命令,这次终于能看到NTFS分区格式选项了。在将优盘成功格式化成NTFS文件系统后,尝试将计算机系统中的大容量高清电影直接拖放到优盘窗口后,系统并没有出现错误提示,一段时间后,文件传输操作结束,这意味着优盘已经能够成功装载大容量文件了。

USB设备的管理另有他途

在计算机系统中使用USB设备是件很平常的事情,用常规的方法访问移动硬盘中的文件,或对移动硬盘执行卸载操作,是十分麻烦的。特别是在计算机系统连接多个USB设备的情况下,要将某个移动设备弹出来,需要经过几个环节才能完成,弹出的USB设备要是没有及时拔出来,再次要访问的话,还需要拔出后重新插上。对于频繁要使用USB设备的用户来说,如何才能对这些设备进行高效管理呢?

其实,巧妙使用外力工具“高级USB管理工具”,就能轻松实现一键管理USB设备的目的。将“高级USB管理工具”下载安装到本地计算机系统,插入USB设备后,用鼠标单击系统托盘区域处的控制图标,弹出USB设备列表(如图2所示),选中其中的目标设备选项,再单击之后的“浏览设备驱动器”按钮,就能访问指定USB设备中的文件内容了。

在访问完USB设备后,用常规的方法将其从系统中卸载掉时,往往要经过好几个步骤,现在有了“高级USB管理工具”后就方便多了。用鼠标单击系统托盘区域处的控制图标,从弹出的USB设备列表中,选择目标USB设备,执行“设备现在可以安全移除”命令,此时就能安全地将USB设备从系统中拔除出来了。

倘若USB设备已经被成功卸载,但是还没有从计算机系统中拔出来时,我们又突然改变注意,想要再次访问USB设备时,根本没有必要再将设备拔出、插入,只要用鼠标再次点击系统托盘区域处的控制图标,从弹出的USB设备列表中,选择已经卸载的USB设备,就可以将其工作状态恢复正常了。如果想提高管理效率,我们还能对专门的USB设备定义恢复、卸载功能键,要做到这一点,可以用鼠标选中USB设备列表中的特定设备,按下对应盘符下的“菜单”按钮,从中逐一点选“设置属性”|“设备管理”选项,将其后界面中的“使用单独的全局热键停止该设备”选项,再设置好合适的调用功能键,最后单击“确定”按钮保存设置操作。日后,只要插入特定的USB设备,就能使用事先指定的功能热键来卸载或恢复该设备了,整个过程不会对其他USB设备的工作造成任何影响。倘若我们有多个USB设备需要恢复、卸载时,可以按照上面的操作方法为它们依次设置好各自的调用功能键,以提高USB设备管理效率。

现在,不少用户已经不仅仅在本地调用USB设备了,他们常常会将一些重要数据文件保存到USB设备上,然后通过Internet或局域网进行异地访问或办公,此时借助“高级USB管理工具”,就能轻松实现一键运行USB设备中的应用程序。在进行这种管理操作时,可以先用鼠标点击系统托盘区域处的控制图标,从弹出的USB设备列表中,选择特定USB设备,按下“快速启动菜单”按钮,点击“添加程序”命令,定位到特定USB设备中某个应用程序的主执行文件上,按下“确定”按钮,日后只要插入特定USB设备,就能从快速启动菜单中看到之前定位的应用程序名称,点击该程序名称后,就能达到快速启动应用程序的目的了。

USB设备上有黄色感叹号

有的时候,USB设备插入到Windows 7系统环境下,对应设备不能正常工作。用鼠标右键单击系统桌面上的“计算机”图标,执行“管理”命令,展开计算机管理窗口,选中设备管理器分支,切换到系统设备管理器窗口时,会发现USB设备上有黄色感叹号标志,同时设备名称变成了“USB Device”,很多菜鸟用户对该现象不知道如何应对。

事实上,当系统设备管理器窗口的设备名称上出现黄色感叹号标志时,往往都是由于设备驱动程序发生了错误所造成的。对待这类问题,往往可以按照下面的操作步骤来解决:

首先可以选中设备管理器窗口中不能正常工作的USB设备,用鼠标右键单击该设备,执行右键菜单中的“卸载”命令,将目标设备从系统中卸载干净,之后执行右键菜单中的“刷新”命令,将系统设备列表刷新一下,这样Windows 7系统就能自动重新安装USB设备的驱动程序了。

倘若Windows系统无法自动搜索到USB设备的驱动程序,不妨利用Windows系统的补丁升级功能,来自动搜索匹配合适的设备驱动程序,成功安装后就能恢复USB设备的正常工作状态了。

当然,如果从网上无法搜索到相匹配的设备驱动程序时,我们可以采用手工方法,下载与Windows 7系统相兼容的设备驱动程序,比方说,某个USB设备只有Vista系统下的驱动程序,而没有Windows 7系统下的驱动程序,此时手工下载好适合Vista系统的驱动文件。接着,用鼠标右键单击出现问题的USB设备,点击右键菜单中的“属性”命令,弹出目标设备的属性对话框,选择“驱动程序”标签,切换到如图3所示的标签设置页面,单击“更新驱动程序”按钮,打开驱动文件选择对话框,导入之前下载好的驱动文件,按下“确定”按钮,完成设备驱动程序的更新操作,这样USB设备就能正常工作了。

USB设备数据不能访问时

在频繁插拔之后,USB设备很容易出现数据内容无法访问的问题。这不,小杨最近遇到一则问题,就是将USB设备连接到计算机系统的USB接口中后,尽管Windows系统能够正常识别出对应USB设备的分区符号,不过用鼠标双击该分区符号后,他看到该设备没有响应,再次双击鼠标时,系统弹出了无法访问的错误提示。见到这样的提示,小杨身上惊出了一声冷汗,毕竟他的USB设备中保存了太多的单位工作文档,这该如何是好啊?

为了不让数据丢失,小杨请来了笔者。对于这样的问题,在笔者看来基本就是小菜一碟,因为每年笔者总要处理好几起同样的USB设备无法读取问题。在处理这类问题时,笔者先从网上下载专业磁盘管理工具DiskGenius,使用WinRAR之类的解压工具将其释放到临时文件夹中,双击该文件夹中DiskGenius工具的主执行文件,切换到对应程序主操作界面。在该界面左侧列表区域,就能直观地看到所有磁盘分区的详细信息,其中包括已经连接到计算机系统中的USB设备对应分区符号。

接着用鼠标左键单击USB设备对应分区图标,这时DiskGenius工具就会自动强制访问USB设备中的目录分支,从该分支下面找到保存在USB设备中的重要文件或文件夹内容,然后用鼠标右键单击目标文件或文件夹,选择右键菜单中的“复制到”命令,弹出文件或文件夹保存对话框,设置好保存路径后,DiskGenius工具就能自动将USB设备中的重要文件或文件夹内容拷贝到指定路径。

倘若USB设备中的数据文件已经受到损坏而无法移动时,不妨用鼠标右键单击指定的USB设备,执行右键菜单中的“已删除或格式化的文件恢复”命令(如图4所示),这样DiskGenius工具就能自动恢复USB设备中受损的数据文件,当然数据恢复操作进程相当缓慢,可能需要等待很长时间,这点一定要有心理准备。如果数据受损程度非常严重,DiskGenius工具也有可能不会将USB设备中的数据恢复成功。

远程桌面不能连接USB设备

为了提高访问效率,有的用户可能会利用Windows系统内置远程桌面连接程序,来远程访问局域网中的共享资源。在远程桌面连接共享资源时,一般都要对保存共享资源的有关设备进行重定向。要做到这一点很容易,只要逐一点选“开始”|“程序”|“附件”|“远程桌面连接”选项,切换到远程桌面连接对话框,按下“选项”按钮,展开远程桌面连接设置区域,选择“本地资源”选项卡,在对应选项设置页面的“本地设备和资源”位置处,选中磁盘驱动器或打印机等选项,日后当远程桌面连接成功后,磁盘驱动器或打印机设备就会被自动重定向到远程主机系统中,这么一来用户就能轻松在远程系统中访问本地共享资源了。

可是,远程桌面连接程序并不支持USB设备的重定向功能,也就是说,当我们尝试从局域网的其他计算机系统中远程访问本地计算机USB设备中的共享资源时,是无法实现的。在USB设备应用日益广泛的今天,如何才能解决远程桌面程序不能连接USB设备的问题呢?

经过上网搜索相关信息,笔者终于找到了解决方案,巧妙使用专业工具USB For Remote Desktop,就能很方便通过远程桌面程序访问USB设备中的共享资源,当然该工具有客户端、服务端版本之分。

为了通过远程桌面连接程序访问本地计算机中的USB设备,首先要从网络上下载获取USB For Remote Desktop客户端程序,按照默认设置将其正确安装到本地系统中,之后从系统“开始”菜单中点击“USB For Remote Desktop(workstation)”选项,来打开USB For Remote Desktop工具的客户端程序界面,如图5所示。选择这里的“My Computer”分支,在该分支下面就能看到连接到本地计算机中的所有USB设备,选中需要让人远程访问的某个USB设备,再从菜单栏中逐一点选“USB Device”|“Redirect”命令,稍微等一会儿,指定USB设备图标上就会弹出绿色感叹号标志,这说明重定向USB设备操作已经成功,这时指定USB设备已经能被远程系统识别到了。要是点击了“Redirect”命令后,指定USB设备图标上弹出红色感叹号标志时,就意味着重定向操作没有成功。

当然,为了提高操作效率,我们可以对USB For Remote Desktop客户端程序进行合适设置,让特定USB设备能够实现自动重定向目的。只要逐一点选主程序界面中的“Settings”|“Preferences”选项,切换到参数设置对话框,选择“Auto-Redirecting”选项卡,打开如图6所示的选项设置页面,将这里的“Enable auto-redirecting of USB devices”选中,按下“确定”按钮返回,这样接到本地计算机中的USB设备就能自动被重定向了。如果不想将某些USB设备自动设置成重定向状态时,不妨选中“do not redirect these devices”列表中的特定USB设备,那样一来该USB设备就不会被自动重定向了。

当完成USB设备的重定向操作后,下面我们就能在其他计算机系统中通过USB For Remote Desktop服务端程序,与客户端系统成功建立远程桌面连接,并通过远程连接访问USB设备中的共享资源了。启动运行USB For Remote Desktop服务端程序,在“Terminal Server”列表中找到连接在客户端系统中的USB设备,接着打开计算机窗口,就能象访问本地文件一样来远程访问USB设备中的共享文件了。

USB设备驱动程序 篇3

关键词:USB系统结构,USB驱动程序,WDM分层结构,DM设备驱动程序,DriverStudio

0引言

随着微机技术水平的日益提高,传统的计算接口已经不能满足当前计算机高速发展的需求,计算机业界迫切需要新的通用型、高速总线接口。通用外设接口标准USB应运而生。而在开发USB设备时,设备驱动程序的设计是其中一项重要的技术环节,它直接影响整个设备系统的性能。

1 USB简介

在众多的PC机总线中,USB以其突出的优点独树一帜:1) 使用方便,即插即用。2) 传输速率高,速度可高达480Mbps。3) 易于扩展。通过使用Hub扩展可连接多达127个外设。4) 使用灵活。USB共有4种传输模式:控制、同步、中断、批量,以适应不同设备的需要。5) 能够采用总线供电。正由于上述特点,开发USB接口的设备已成为一种发展趋势。

1.1 USB系统结构

一个完整的USB系统包括主机系统和USB设备。所有的传事务都是由主机发起的。一个主机系统又可以分为以下几个层次结构,如图1所示:

USB总线接口包括USB主控制器和根集线器,其中USB主控制器负责处理主机与设备之间电气和协议层的互连,根集线器提供USB设备连接点。USB系统使用USB主控制器来管理主机和USB设备之间的数据传输。应用软件通过USB系统和USB总线接口与USB设备进行交互。

USB设备包含一些向主机软件提供一系列USB设备的特征和能力的信息的设备描述符,用来配置设备和定位USB设备驱动程序。这些信息确保了主机以正确的方式访问设备[1]。

1.2 USB接口软件结构

一个完整的USB接口软件结构包括PC机底层驱动程序、USB固件程序、USB功能驱动程序以及PC机应用程序。PC机底层驱动程序负责处理总线枚举、电源管理以及USB事务等,Windows操作系统已经提供。编程者需要开发的程序为:USB控制器固件程序、设备功能驱动程序、PC机应用程序。

USB控制器固件程序实现设备的枚举以及端点与主机的通信。设备功能驱动程序为应用程序和底层驱动程序之间提供接口。PC机应用程序功能是为用户提供一个友好的可视化操作界面。

2 Windows驱动程序模型(WDM)

Windows环境下驱动程序共有三类,一类是VxD( Virtual Device Driver),用于Windows 95/98/Me操作系统中;一类是KMD(Kernel Mode Driver),用于Windows NT下;还有一类就是WDM(Win32 Driver Mode),是微软从Windows 98开始,推出的一个新的驱动类型,它是一个跨平台的驱动程序模型[2]。

WDM旨在实现对新硬件支持的基础上,进一步降低所需要驱动程序的数量和复杂性,以简化驱动程序的开发。WDM属于操作系统的内核模式,其驱动程序由运行于内核模式的系统代码组成,它为Windows操作系统的设备驱动程序提供了统一的框架,在Windows平台上,WDM将成为主流的驱动模式。

2.1 WDM驱动程序分层结构

WDM采用分层驱动的方法,不同层次上的驱动程序可以相互调用。为适用于即插即用系统,WDM重新定义了驱动程序的分层结构,其主要包含以下三种类型的驱动程序:总线驱动程序、功能驱动程序和过滤驱动程序,每层驱动把I/O请求划分成更简单的请求,以传给更下层的驱动执行。最底层的驱动程序在收到I/O请求后,通过硬件抽象层,与硬件发生作用,从而完成I/O请求工作[3]。

WDM引入设备对象的概念来描述一个设备,主要包括功能设备对象FDO(Function Device Object)、物理设备对象PDO(Physical Device Object)和过滤设备对象Filter DO(Function Device Object),一个PDO对应一个真实的硬件,FDO和Filter DO是相应的驱动程序处理对象。WDM驱动程序直接操作的不是硬件本身,而是相应的PDO、FDO和Filter DO。驱动程序和设备对象的分层情况如图2所示。

总线驱动程序位于最底层,创建PDO,负责驱动I/O总线,处理总线上全部事务,控制对其总线上所有设备的访问。功能驱动程序分层在总线驱动的上面,创建FDO,用于驱动一个单独的设备,控制特定设备的主要功能,是设备的主要驱动程序。过滤驱动程序用于过滤发向设备、设备类或总线的I/O请求,可分为下层过滤驱动程序和上层过滤驱动程序,它是可选的。

2.2 WDM驱动程序的组成

一个WDM驱动程序包括以个5个例程:

1) 驱动程序入口例程:处理驱动程序的初始化。

2) 即插即用例程:处理PnP设备的添加、删除和停止。

3) 分发例程:处理用户应用程序发出的各种请求。

4) 电源处理例程:处理电源管理请求。

5) 卸载例程:处理驱动程序的卸载。

2.3 USB驱动程序的WDM结构

对于USB设备来说,其WDM驱动程序分为USB底层(总线)驱动程序和USB功能(设备)驱动程序。USB驱动程序符合Windows 2000下的内核模式驱动程序的分层体系结构,如图3所示:

USB底层驱动程序由操作系统提供,负责与实际的硬件打交道,实现烦琐的底层通信。USB功能驱动程序由设备开发者编写,不对实际的硬件进行操作,而是通过向USB底层驱动程序发送包含URB(USB Request Block,请求块)的IRP,来实现对USB设备信息的发送和接收。

USB驱动程序工作简述如下:应用程序对USB设备进行I/O操作时调用Windows API函数,I/O管理器将此请求构造成一个合适的I/O请求包(IRP)并把它传递给USB功能驱动程序。USB功能驱动程序接收到这个IRP后,构造相应USB请求块(URB)并把它传递给USB底层驱动程序。USB底层驱动程序执行相应的操作,并把操作的结果返回给USB功能驱动程序。USB功能驱动程序接收到此返回的IRP后,将操作结果通过IRP返还给I/O管理器,最后I/O管理器将此IRP操作结果传回给应用程序,至此应用程序对设备的一次I/O操作完成。

2.4 USB设备驱动程序开发工具

开发USB设备驱动程序需要专门的开发工具,目前应用广泛的工具主要有两大类。

一类是Microsoft公司提供的Windows DDK(Device Driver Kit)。由于DDK基于汇编语言的编程方式和内核模式的调用,对没有深厚的OS原理和编程水平的人员来说,任务相当艰巨。

另一类是NuMega公司提供的DriverStudio,它是一个大的开发工具包,包含VtoolsD、SoftICE和DriverWorks等开发工具。DriverWorks,提供了VC++下的开发向导Driver Wizard,按照它的提示可以迅速地生成驱动程序的框架,开发者可以在此基础上根据各自的需要添加自己的代码。利用DriverWorks开发WDM驱动程序,可以大大简化开发人员的工作量、缩短开发周期以及降低开发驱动程序的难度[4]。

3用DriverWorks开发WDM型USB设备驱动程序

下面就用一个简单的例子说明用DriverWorks开发WDM型USB设备驱动程序的方法。

3.1搭建开发平台

1) 在已装了Windows 2000操作系统的机子上安装Microsoft Visual C++6.0。

2) 安装Win 2000 DDK。

3) 安装NuMega DriverStudio驱动程序开发工具包。

4) 由于DriverWorks所用的类库是对DDK函数的封装,必须在VC中编译,创建自己的库文件。

5) 设置DDK路径。

3.2利用DriverStudio 的DriverWorks生成USB设备驱动程序框架

驱动程序开发平台搭建成功后,我们可利用驱动程序生成向导Driver Wizard,根据硬件设置较为容易的生成USB设备驱动程序的大体框架。设置如下:1) 选择WDM的驱动程序类型和Windows 2000运行平台。2) 选择USB总线类型,填写它的VID(供应商ID)和PID(设备ID),这些信息由芯片的供应商提供。3) 增加端点(可连续增加多个),并分别设置其IN/OUT属性以及端点地址。4) 根据需要选择对设备的操作如Read、Write、Device Control和CleanUp等。5) 可根据需要选择给端点n产生BULK Read或Write的代码,向导会自动产生一套对端点n进行读或写的代码。6) 设置驱动程序的属性,采用WDM接口;在选取读写方式时应遵循一条原则:需要快速传送大量数据时,用Direct I/O,反之用Buffer I/O;7) 增加IOCTL接口,在其生成的代码框架中加入自己的操作,以实现一个完整的USB设备驱动程序。最后就生成了一个WDM型的USB设备驱动程序框架和一个测试该驱动程序的测试程序大体框架。然后在其中添加需要的功能代码,主要是添加相应的IOCTL代码以实现用户需要的操作。

至此,一个简单的USB功能驱动程序就完成了。

4 INF文件的介绍

要想正确安装设备驱动程序必须而要编写相应的INF文件,INF文件含有安装一个WDM设备驱动程序需要的所有必要的信息,如该设备使用哪个驱动系统注册表中应存储哪些信息等,以确保其硬件设备能被正确配置和安装。

当系统发现新的设备时,就调用Windows的“添加新设备向导”执行。这个向导扫描并选择与其兼容供应商ID与设备ID最佳匹配的INF文件,若未找到提示用户选择驱动程序INF文件。然后根据INF文件的指令安装驱动程序,驱动程序被装入内存,并执行相应的例程。启动设备,正常的I/O操作就可以继续进行。

当用DriverWorks开发USB驱动程序时,DriverWorks会同时生成一个INF文件,用户只需根据要求修改相应节内容即可。

5 PC机应用程序的实现

当正确安装好USB功能驱动程序后,用户可以编写相应的PC机应用程序实现与USB设备的通讯。在Windows中,Win32应用程序调用WDM的Win32函数有五个:CreateFile(),ReadFile(),WriteFile(),DeviceIocontrol(),CloseHandle()。

1) 打开一个WDM设备

应用程序调用CreateFile()函数打开一个WDM设备驱动程序,它的第一个参数是一个符号链接名。调用CreateFile()函数获得设备的句柄,这将产生对应于此设备对象的IRP。

2) 关闭一个WDM设备

WDM允许多个应用程序打开同一个设备,它为每个应用程序创建一个设备对象。当其中的一个应用程序调用CloseHandle()函数,驱动程序收到“清除”IRP并在“清除”例程中清除和此设备对象有关的待处理的IRP。然后关闭设备对象。

3) ReadFile()、WriteFile()和DeviceIoControl函数的调用。

这些调用都产生一个请求,产生IRP请求包传递给驱动程序,实现对设备的读、写和一些由用户定义的特定操作。

6结束语

随着USB技术的不断发展和完善,开发一些特定功能的USB接口并设计其设备驱动程序已将成为应用USB技术的关键。通过对USB的学习和Windows 2000下的WDM驱动程序的研究,本论文简单介绍了WDM驱动程序模型,并给出了编写WDM型USB设备驱动程序的一般方法,给初学者提供了一个很好的向导。

参考文献

[1]李英伟.USB2.0原理与工程开发[M].北京:国防工业出版社,2006.

[2]张惠娟.indows环境下的设备驱动程序设计[M].西安:西安电子科技大学出版社,2002.

[3]孙义.WindowsWDM设备驱动程序开发指南[M].北京:机械工业出版社,2005.

USB设备驱动程序 篇4

Linux是一种日趋成熟完善的操作系统, 其源代码公开、结构清晰、功能强大等特点而广泛使用, 越来越多的软硬件厂商开始使用Linux平台来开发自己的产品, 基于该平台的设备驱动程序的需求也愈来愈多[1,2]。

通用串行总线 (USB) 是一种外部总线结构, 特点是接口统一、易于使用、方便扩展、支持热插拔和即插即用[3,4]。Linux的2.6 内核支持USB2.0 规范。分析了Linux 中USB 协议的具体实现机制, 并开发了一个特定USB 设备驱动驱动程序。

1 USB体系结构和驱动层次

1.1 USB体系结构

USB总线体系结构采用分层的星型拓扑来结构连接所有设备, 包括主机、设备、连接三个部分, 最多支持7层如图1所示。USB主机完成主机和USB设备之间的数据传输, 在数据传输过程中处于主导地位, USB设备只能响应USB主机的命令。按照USB设备功能的不同, 可以分为两大类:USB集线器和USB功能设备[5]。USB集线器为USB主机连接多个功能设备提供了USB端口, 在USB系统中USB集线器可以级联5级。USB功能设备用于扩展USB主机的功能, 满足用户需求的独立外部设备。此外, USB总线拓扑结构中允许把USB集线器和USB功能设备组合在一起的复合设备出现。USB连接是指USB设备与主机连接及通信的方式, 包含总线拓扑、层次关系、数据流模型、USB调度等等。

1.2 USB驱动层次

在Linux系统中USB驱动层次如图2所示。

在主机侧, USB主机控制器驱动用于USB控制器来控制USB设备的行为, 而USB设备驱动控制USB设备与主机通信与设备通信的方式, 这两层是驱动程序主要实现的。USB核心在USB驱动程序开发中是非常重要的, 它实现的USB驱动管理和协议处理的主要工作。在USB核心中定义了一些重要的数据结构、宏和功能函数, 分别为USB设备驱动和USB主机驱动提供编写驱动程序的接口[6]。设备侧的驱动在USB固件中实现。

2 USB驱动程序结构

所有USB驱动程序都必须创建的主要结构体是struct usb_driver。该结构体必须由USB驱动程序来填写, 包括许多调用函数和变量, 它们向USB核心代码描述了USB驱动程序[7]。在<linux/usb.h>中的定义如下:

struct usb_driver {

struct module*owner;

const char*name;

const struct usb_device_id*id_table;

int (*probe) (struct usb_interface*intf,

const struct usb_device_id*id) ;

void (*disconnect) (struct

usb_interface*intf) ;

int (*ioctl) (struct usb_interface*intf,

unsigned int code, void*buf) ;

int (*suspend) (struct

usb_interface*intf u32 state) ;

int (*resume) (struct

usb_interface*intf) ;

};

主要的工作由probe () 和disconnect () 函数, 即探测和断开函数完成, 它们分别在设备被插入和拔出的时候被调用, 用于初始化和释放软硬件资源。对usb_driver的注册和注销通过这两个函数完成:

int usb_register (struct usb_driver

*new_driver) ;

void usb_deregister (struct usb_driver

*driver) ;

usb_driver起到了牵线的作用, 即在probe () 里注册设备, 在disconnect () 函数中注销设备, 原先对设备的注册和注销一般直接发生在模块加载和卸载函数中。

3 USB串口设备驱动程序的实现

USB设备驱动程序主要包含usb_driver结构体中的成员函数和tty_operations结构体中的操作。usb_driver结构体中最主要的函数探测和断开函数分别为usb_serial_probe () 和usb_serial_disconnect () 。USB串口设备驱动的tty_operations结构体封装了设备驱动的成分, 其结构体实例serial_ops定义如代码如下:

static struct tty_operations serial_ops = {

.open =serial_open,

.close =serial_close,

.write =serial_write,

.ioctl =serial_ioctl,

.set_termios =serial_set_termios,

.throttle =serial_throttle,

.unthrottle =serial_unthrottle,

.chars_in_buffer

=serial_chars_in_buffer, ……

};

它们实现了USB串口设备的打开、关闭、写、控制等各项功能, 是串口设备的各种操作可以得到执行。

4 结束语

Linux操作系统以其免费、源代码开放、效率高等特点, 广泛的应用于嵌入式系统中。USB的快速发展使其不断取代了串并口等传统外部接口成为外部设备与PC之间数据传输的主要通道。本文的对USB驱动程序的研究和开发对Linux嵌入式系统开发有一定的参考。

参考文献

[1]陈胤.Linux操作系统的应用现状和推广策略[J].计算机时代, 2006 (4) :42-44.

[2]宋磊, 甄奇, 张涛.一种基于Linux的嵌入式软件开发支撑环境[J].军事通信技术, 2008, 28:1-5.

[3]肖踞雄, 翁铁成, 宋中庆.USB技术及应用设计[M].北京:清华大学出版社, 2003:4-9.

[4]杨伟, 刘强, 顾新.Linux下USB设备驱动研究与开发[J].计算机工程, 2006, 32 (19) :283-284.

[5]马尾.计算机USB系统原理及主从机设计[M].北京:北京航空航天大学出版社, 2004:172-187.

[6]宋宝华.Linux设备驱动开发详解[M].北京:人民邮电出版社, 2008:563-564.

USB设备驱动程序 篇5

USB软件系统一般由三部分组成:应用程序、USB设备驱动程序(也称客户驱动程序)和系统USB类驱动程序(USBD.SYS)。USB设备驱动程序控制一个给定的USB功能设备,它把USB设备看作是一个可以被访问端点的集合,USB设备可以被控制并与它的功能单元通信。USBD是由Windows操作系统自带,它提供了一个编程接口USBDI(USB device interface),USB设备驱动程序就是通过USBDI来传输请求,实现对USB设备的控制。而应用程序必须通过USB设备驱动程序与系统USBD进行通信。

USB定义了四种传输类型:控制传输、同步传输、批量传输、中断传输。USB对不同类型的外部设备与主机之间的管道要求不同的传输类型,以在该管道的客户软件与功能设备之间形成高效率的传输机制[2]。控制传输是在主机与控制端点之间传送控制信息。每个USB设备至少应有一个编号为0的控制端点以响应控制事务的输入输出,当一个USB设备连入USB系统时,系统软件必须通过控制传输读取该设备的描述符以确定该设备的类型和操作特性。中断传输在总线操作和涉及设备方面上几乎与批量传输完全相同,它能把最大64字节的数据无误地在主机和中断端点之间传输,中断传输和批量传输仅有的不同是它必须考虑延迟。中断端点需指定一个范围在1-255毫秒的查询周期,这种传输方式典型地应用在少量的、分散的不可预测数据的传输。对于中断传输,当USB设备向主机发送数据时,主机必须能够及时知道并且先向要发送数据的设备发出一个请求,设备才能开始发送数据。即USB不支持硬件中断,采用中断传输的USB设备不能够用传统的中断方式中断主计算机,而是提供中断端点供USB设备驱动程序周期性地查询。也就是说,在USB设备传送数据之前,应用程序需一直处于循环查询状态,以确定是否有数据要传输。这就存在很大的缺陷,因为应用程序在进行循环查询时,就不能再做别的事情了,这样很容易造成线程阻塞而影响系统的稳定性。

由于外部事件发生时间的不确定性,程序设计者在编写采用中断传输的USB设备驱动程序时,首先要考虑的问题是如何查询USB设备才能不丢失外部中断数据,其次是在USB设备驱动程序获得中断数据后,如何通知应用程序,既让应用程序能够及时取走数据又不造成线程阻塞。笔者在开发基于USB的监控系统时,很好地解决了上述问题。本文就是根据作者的实践经验,详细阐述实现USB随机中断传输的设备驱动程序设计方法。

1 实现原理

WDM(Windows Driver Model)是微软提出的一种全新的设备驱动程序模型。它是在 Windows NT内核驱动程序模型(Kernel_model Driver Mode)的基础上发展起来的,增加了对即插即用(PnP)、高级电源管理、Windows管理接口(WMI)的支持。更重要的是,WDM是一种通用的驱动模式,提供了包括USB、IEEE1394和HID等在内的一系列驱动程序类。在 Windows 2000和Windows XP中,WDM驱动程序均可正常使用。

1.1 USB驱动程序的WDM结构

USB驱动程序的构成层次如图1所示。其中USB设备驱动程序通过Windows系统提供的USB类驱动程序接口(USBDI)与下层驱动程序通信[3]。

在USBDI的基础上进行编程将大大简化驱动程序设计的工作,用户不用关心IRP的类型,而只需要在相应的分发例程中通过构造USB块并将其通过USBDI发送下去就可以实现对USB设备的控制了。

1.2 USB中断传输驱动程序的实现方法

与传统PCI总线设备的驱动程序相比,USB设备驱动程序从不直接与硬件对话。相反,它仅靠创建URB(USB请求块)并把URB提交到总线驱动程序就可完成硬件操作。在对USB中断管道进行读写时,由于设备驱动程序需要按照端点指定的周期进行循检,一般的做法是在驱动程序中建立独立线程来对端点按一定的时间间隔(一般不大于32ms)进行循环检测。但是,由于驱动程序同时需要处理即插即用和电源管理,这将使对独立线程的管理变得非常复杂。因此,本文的做法是:在驱程中增加一个自定义的辅助函数StartPolling,该函数的主要功能是创建一个读请求的URB,并把URB发送给USBD。我们在驱程的OnStartDevice例程完成对USB的配置,设备被激活时就调用这个函数来发送URB。由于设备中断事件的随机性,在设备中断数据未传送之前,该URB一直处于未完成状态。设备中断数据传送之后,若URB返回错误代码,就停止发送URB。若URB返回读成功代码,就会自动调用我们编写的读完成例程InterruptTransferComplete,在InterruptTransferComplete例程中,一方面通知应用程序读取数据,一方面再次发送URB来等待读取下次中断数据。这样就可以始终维持一个活动的URB,既可以使主机自动循检中断端点,又不增加管理独立线程的负担。

1.3 驱动程序与应用程序的通信

驱动程序与应用程序运行于不同的环境而又紧密合作,但是应用程序通知驱动程序比较容易(如直接调用API函数:ReadFile、WriteFile、DeviceIoCtrol等)。而驱动程序通知应用程序却不太容易。本文采用WIN32事件通知方法,也就是由应用程序创建事件后,通过DeviceIoCtrol函数直接将该事件句柄传递给驱动程序。当驱动程序捕捉到中断事件发生时,驱动程序在获取中断数据后就可以设置事件信号状态来触发应用程序读取数据。

2 设备驱动程序设计

本实例采用Philips PDIUSBD12 SMART Evaluation Borad作为USB设备,设备固件定义了一个中断端点。该板上有两个按键,每次当按下SMART开发板上的按键时,固件就向中断端点送出4字节数据,在下一个主机IN事务时中断端点将交付这4个字节。设备驱动程序不断地尝试读该端点并累加所发生的中断数,把接收到的中断数据和累加数一起传给测试程序。测试程序发出DeviceIoControl调用来读出数据并显示结果。以下是实现中断传输的驱动程序主要代码:

2.1 驱动程序编程

在OnStartDevice例程中,首先读取设备描述符,若描述符中的厂商代码与指定的厂商代码相符合,则激活USB设备。若激活成功,则调用StartPolling(pIntBuff,IntBuffLen)函数构造读请求URB并发送URB到总线。其中的pIntBuff是指向接收缓冲区的指针,IntBuffLen是要读取的字节数。

NTSTATUS spo2_devDevice::OnStartDevice(KIrp I)

{USB_DEVICE_DESCRIPTOR desc;

status=m_Lower.GetDeviceDescriptor( &desc );

if ( !NT_SUCCESS(status) ){ return status;}

if(desc.idVendor==0x0471 && desc.idProduct==0x0666)

{acStatus=m_Lower.ActivateConfiguration(1); //激活USB

if (!AC_SUCCESS(acstatus) ){ return acstatus;}

StartPolling(pIntBuff,IntBuffLen);} //开始循检中断端点

应用程序通过调用DeviceIoCtrol函数把控制代码和缓冲区地址发送给驱动程序,驱动程序的DeviceControl(KIrp I)例程就是根据应用传来的控制代码完成相应的操作。其中IOCTL_INTERRUPT_EVENT部分是接收应用程序传来的事件句柄,并构造系统事件。而IOCTL_INTERRUPT_GET_DATA部分是应用程序在获得事件通知后,发来的读中断数据控制码。m_bNotifyApp初试化状态为TRUE,当有中断发生时,驱动程序设置事件,通知应用程序取数据;在应用程序取数据之前,设置m_bNotifyApp为FALSE,这样一来,即使再有中断发生,驱动程序也不再通知应用程序了;只有应用程序取数据之后,设置m_bNotifyApp为TRUE,再有中断发生,驱动程序才会通知应用程序。

NTSTATUS spo2_devDevice::DeviceControl(KIrp I){

switch (I.IoctlCode())

{

case IOCTL_INTERRUPT_EVENT:

{HANDLE hEvent=*(HANDLE*)I.IoctlBuffer(); //应用程序创建的事件句柄

if (m_pEvent) delete m_pEvent;

m_pEvent=new(NonPagedPool)KEvent(hEvent, OBJECT_TYPE_ALL_ACCESS);

return I.Complete(STATUS_SUCCESS);}

break;

case IOCTL_INTERRUPT_GET_DATA: //把数据传送给应用程序

{m_bNotifyApp=TRUE;

PUCHAR p2=(PUCHAR)I.IoctlBuffer();

RtlCopyMemory(p2,pIntBuff,IntBuffLen);

Information()=IntBuffLen;

return I.Complete(STATUS_SUCCESS);}

break;}

StartPolling的主要功能是构造、发送URB,并连接到回调函数InterruptTransferComplete。m_lPolling是指示URB的状态:若成功返回为0,若未完成则为1。

NTSTATUS spo2_devDevice::StartPolling(PVOID Buffer,ULONG Length,PVOID pClientContext)

{m_pIntUrb=new URB;

if( NULL==m_pIntUrb )

{return STATUS_INSUFFICIENT_RESOURCES;}

m_KIrp=KIrp::Allocate( m_Lower.StackRequirement() );

if( m_KIrp==NULL)

{delete m_pIntUrb;

return STATUS_INSUFFICIENT_RESOURCES; }

PINT_COMPLETION_INFO pCompInfo=new (NonPagedPool) INT_COMPLETION_INFO;

if( NULL==pCompInfo )

{return STATUS_INSUFFICIENT_RESOURCES; }

pCompInfo->m_pClass=this;

pCompInfo->m_pUrb=m_Pipe1.BuildInterruptTransfer(Buffer,Length,TRUE,NULL,m_pIntUrb);

status=m_Pipe1.SubmitUrb(m_KIrp,m_pIntUrb,LinkTo(InterruptTransferComplete),pCompInfo);

InterlockedExchange(&m_lPolling, 1);

return status;}

在有中断数据传来,读请求成功返回时会自动执行InterruptTransferComplete函数,该函数主要实现的功能是:对中断累加计数、设置事件状态和重新构造URB并发送URB到总线,用相同的URB初始化另一轮中断循检。

NTSTATUS _stdcall

spo2_devDevice::InterruptTransferComplete(KIrp I, PINT_COMPLETION_INFO pContext) { NTSTATUS status;

InterlockedExchange(&m_lPolling, 0);

m_NumInterrupts++; //中断次数计数

if (m_pEvent) {pIntBuff[4]=m_NumInterrupts;

if(m_bNotifyApp) { m_pEvent->Set(); //设置事件

m_bNotifyApp=FALSE; }}

if(NT_SUCCESS(I.Status())&&(1!=INTERLOCKED_COMPARE_EXCHANGE(&m_lStopRequested, 1, 1)))

{memset(&reinterpret_cast<_URB_BULK_OR_INTERRUPT_TRANSFER*>(m_pIntUrb)->hca,

0,sizeof(_URB_HCD_AREA));

m_KIrp.Reuse();

InterlockedExchange(&m_lPolling, 1);

pContext->m_pUrb=m_Pipe1.BuildInterruptTransfer(pIntBuff,IntBuffLen,TRUE,NULL,m_pIntUrb);

m_Pipe1.SubmitUrb(m_KIrp,m_pIntUrb,LinkTo(InterruptTransferComplete),pContext);

return STATUS_MORE_PROCESSING_REQUIRED;}

delete pContext;}

本驱动程序利用DriverWorks编程,在Windows XP DDK编译通过。

2.2 应用程序设计

以下是应用程序中读取中断数据的子线程。该子线程以同步方式打开设备后,创建自动重置事件句柄传递给驱动程序,然后等待事件发生。当事件发生后,就读取数据并利用SendEvent函数向主线程发送消息,通过主线程显示中断数据和中断次数。程序运行结果如图2所示,其中前四个数据由USB设备传来,第五个数据是驱动程序对中断次数计数。

UINT ServiceThread(LPVOID pParam) {

HANDLE m_hDevice,m_hEvent;

ULONG nItems, nBytesRead,i;

PUCHAR tsbuf;

CString msg,s1;

KeepRunning=FALSE;

m_hDevice=open_dev(); //以同步的方式打开USB设备

tsbuf=new UCHAR[8];

if (m_hDevice==INVALID_HANDLE_VALUE)

{msg.Format(″Cannot open device, error 0x%xn″, GetLastError());

Print_Event::SendEvent(msg);

return 1;}

m_hEvent=CreateEvent(NULL, FALSE, FALSE, NULL); //创建自动重置事件

if(!DeviceIoControl(m_hDevice,IOCTL_INTERRUPT_EVENT,&m_hEvent,sizeof(m_hEvent),NULL,0,&nBytesRead,NULL)) //传递事件句柄

{CloseHandle(m_hDevice);

CloseHandle(m_hEvent); //关闭事件

return 1;}

KeepRunning=TRUE;

while (TRUE){

while(WaitForSingleObject(m_hEvent,0)!=WAIT_OBJECT_0)

{

if (!KeepRunning) {

CloseHandle(m_hDevice);

CloseHandle(m_hEvent);

return 0;}};

if(!DeviceIoControl(m_hDevice, IOCTL_INTERRUPT_GET_DATA ,NULL,0,

tsbuf,8,&nBytesRead,NULL) ) //读取数据

{ CloseHandle(m_hDevice);

CloseHandle(m_hEvent);

return 1; }

for(i=0;i<=4;i++)

{ s1.Format(″%d″,tsbuf[i]);

msg=msg+s1+″,″;}

Print_Event::SendEvent(msg); //显示信息}}

3 结束语

USB总线的成功关键是使用户感到了使用USB设备的方便。USB技术得到广泛应用,进行USB设备驱动程序的开发已经成为必不可少的技术环节。本文所介绍的实现USB随机中断传输的驱动程序设计方法,已成功应用于安全监控系统。该方法具有实现简单、结构清晰、运行稳定等优点,在USB驱动程序设计中具有良好的应用价值。

摘要:USB具有方便快速等优点,已经发展成为一种比较普遍的计算机与外围设备之间的接口。但是,USB设备不能够用传统方式中断主计算机,而是提供中断端点,主机可以周期性地查询中断端点。由于USB设备发生中断的时间不确定性,这就使中断传输的设备驱动程序开发的难度加大。阐述了实现USB中断传输的设备驱动程序和应用程序的设计原则和方法,该方法具有很强的通用性,并经过实践证明具有很好的实用性。

关键词:通用串行总线,中断传输,事件

参考文献

[1]Philips Semiconductors.PDIUSBD12.Specification,1999.

[2]Compaq,Microsoft,Intel,NEC.Universal Serial Bus Specification Revision1.1.1998.

[3]Walter oney.Programming the Windows Driver Model[M].北京:北京大学出版社,2000.

[4]武安河,周利莉.Windows设备驱动程序(VxD与WDM)开发实务.电子工业出版社,2001.

USB设备驱动程序 篇6

在油田开采中,及时准确地测量出油井的液面深度可以有效地保证采油设备的安全运行,并为优化生产提供重要的参数。研究涉及油田油井液面深度约300~3000m。动态液面测量系统采用微处理器控制发射声波,声波通过油管与套管之间环隙中的压缩天然气向井下传播。整根油管由上百个管段和接箍拼接而成。声波在传播过程中,每遇到1个接箍就会产生1个小的回波,最后到达液面会反射1个强的回波,同时由检波器提取声波信号并转化为电信号,信号经调理后进入DSP。利用DSP芯片强大的信号处理能力在微处理器内,通过软件实现滤波和图形识别。但是考虑到回波采集数据量较大(一台仪器一次测量就是1万个数据点),不方便数据显示和管理,故构造嵌入式系统提取各个井深测量仪的井深数据,建立数据的统一管理系统,方便数据显示与管理。见图1示。

1994年,由Compaq,Intel,Microsoft和NEC组成的联盟开始制定通用串行总线标准,即USB(Universal Serial Bus)。图2展示了USB通信模型之间基本的信息流与互连关系。由图可见,主机与设备都被划分成不同的层次。主机上垂直的箭头是实际的信息流。设备上对应的接口是基于不同实现的。在主机与设备之间的所有通信最终都是通过USB的电缆进行,然而,在上层的水平层之间存在逻辑的主机-设备信息流。主机上的客户软件和设备功能部件之间的通信是基于实际的应用需求及设备所能提供的能力。

2 基于DSP平台的动态井深测量仪USB固件驱动

动态井深测量仪基于德州仪器D S P处理器TMS320F2812,使用CCS为交叉编译环境,集成程序编辑、编译、连接、下载和仿真为一体。

动态井深测量仪上采用了Cypress公司的CY7C68001芯片实现USB设备接口。CY7C68001上集成了USB2.0收发器(物理层)、USB2.0串行引擎(链路层,实现底层通信协议)。CY7C68001则作为F2812的外设,USB的应用层协议由F2812编程实现。CY7C68001采用并行异步存储器接口与F2812相连接,主机可以唤醒F2812,也可以配置U S B。

CY7C68001有两个外部接口:

1.命令接口:用来访问CY7C68001寄存器、Endpoint0缓冲器及描述表。

2.FIFO数据接口:用来访问4个1K字节的FIFO中的数据。

图3描述出D S P程序中U S B设备固件部分的驱动流程图。

3 基于ARM下嵌入式Linux的USB设备驱动

3.1 USB协议

U S B包括U S B主控制器和根集线器,U S B连接设备时必须使用集线器(hub)。其中USB主控制器负责主机与设备间的电气和协议的互联,根集线器提供USB设备的连接点。一个完整的U S B系统包括主机系统和USB设备。所有传输事务都由主机发起[1]。

3.2 USB驱动程序的核心数据结构

Linux内核的USB系统提供了与USB设备驱动程序开发相关的一些非常重要的数据结构,在整个驱动开发中起着很重要的作用。

为USB设备文件提供了一个文件界面操作数据结构file_operations结构。其结构几乎全是函数指针,所以实际上是一个函数跳转表,例如read就指向USB设备的读文件操作的入口函数。其中一些主要的函数如下所示:

3.3 USB驱动程序设计

下面对U S B下井深测量仪的设备驱动进行一些简要分析。

(1)USB驱动程序的注册和注销。所有的USB驱动程序在装载时都必须向U S B系统注册,在载卸时向U S B系统注销。这两个过程分别在驱动程序的初始化和退出函数中进行。

(2)USB驱动程序的操作函数。dlm驱动程序的操作主要包括3个部分,即USB驱动程序dlm_driver、设备类驱动程序dlm_class和设备操作函数dlm_fops。dlm_driver描述了主机控制器如何探测设备、断开设备及得到设备信息;dlm_class包括设备的操作函数集和访问权限;dlm_fops描述了对设备文件的读写操作方法[3]。

(3)在Linux内核中,使用usb_driver结构体描述一个USB设备驱动,usb_driver结构体的定义如下所示。

故在动态井深测量仪驱动中实例化一个usb_driver结构体如下:

static struct usb_driver dlm_driver;

3.4 USB驱动程序编写实例

以下以动态井深测量仪(简称dlm)为例,说明USB驱动程序模块的具体编写。

(1)USB驱动程序的注册和注销

USB驱动程序首先要向Linux系统登记,这就是驱动模块初始化过程要完成的操作[4]。

上述dlm_usb_driver是一个struct usb_driver的结构体。当U S B驱动程序卸载时,要向系统注销。调用usb_deregister函数。

当设备插入时,为使Linux hotplug系统自动装载程序,系统就要创建一个MODULE_DEVICE_TABLE来说明这个U S B驱动程序所支持的硬件。USB_DEVICE宏根据制造商ID和产品ID生成一个usb_device_id结构体的实例,在数组中增加该元素将意味着该驱动可支持匹配制造商ID、产品ID的设备,即这里的动态井深测量仪设备中U S B设备芯片C Y 7 C 6 8 0 0 1的制造商ID0x04b4和产品ID0x0082。

USB_DEVICE宏利用制造商ID和产品ID提供了一个设备的唯一标识。当系统插入一个与I D匹配的U S B设备到U S B总线时,驱动程序会在U S B C O R E中注册。驱动程序中p r o b e函数也就会被调用。usb_device结构指针、接口号和接口ID都会被传递到函数中。

驱动程序需要确认插入的设备是否可以被接受,如果不接受,或者在初始化的过程中发生任何错误,probe函数返回一个N U L L值。否则返回一个含有设备驱动程序状态的指针。通过这个指针,就可以访问所有结构中的回调函数。

(2)USB设备的打开和释放

USB设备的打开是通过调用文件操作集中的open()函数来完成,它也是为设备的其他操作做好准备[5]。

(3)USB设备读数据函数

USB设备的读取函数主要是调用usb_bulk_msg()来从动态井深测量仪取数据,然而再拷贝数据到用户区。

(4)编译及挂载文件系统

在编译L i n u x内核时,选中“U S B d e v i c e filesystem”。usbfs动态跟踪总线上插入和移除的设备,通过它可以查看系统中USB设备的信息,包括拓扑、带宽、设备描述符信息、产品ID、字符串描述符、配置描述符、接口描述符、端点描述符等。内核中提供了USB设备文件系统(usbdevfs,Linux 2.6改为usbfs,即USB文件系统),它和/proc类似,都是动态产生的。通过输入命令:mount-t usbfs none/proc/bus/usb可以实现USB设备文件系统的挂载。这样,当我们连接井深测量仪和ARM终端时,查看/proc/bus/usb/devices文件得到当前U S B子系统的结构如下:

从该拓扑文件中可以看出,U S B设备驱动已经探测到动态井深测量仪这个设备,并读取了所有的设备信息和接口、端点信息,表明设备驱动已经成功加载了。

4 结束语

本文将U S B与嵌入式技术应用于石油领域,并对USB从机固件与主机设备驱动都实现了相应开发应用,使得数据通讯操作方便、快捷,为建立油井深度的数据库打下了良好的基础。

U S B总线标准从最初的U S B 1.0发展到现在的USB2.0和USB OTG,传输速度越来越快。Linux作为一种开源的GPL操作系统,其发展前景非常广阔。近年来嵌入式系统的发展,为USB设备与Linux操作系统的互联提供了良好的市场前景。

摘要:USB总线是一种快速、双向、同步、低成本、动态可连接的串行总线,其驱动程序是Linux内核的一个重要组成部分。随着Linux操作系统的广泛应用,特别是嵌入式设备的大量出现,USB驱动程序的编写越来越显得重要了。本文实现了基于DSP平台的USB从机固件开发以及基于ARM下嵌入式linux的USB主机设备类驱动开发。

关键词:嵌入式Linux,USB主机设备驱动程序,USB从机固件

参考文献

[1]Compaq,Hewlett2Packar Universal Serial Bus Specification Revision 2.[Z].[s.l.]Compaq Hewlett2packar,2000.

[2]CORBET J,RUBINI A KROAH HARTMAN GLinux Device Drivers[M].[s.l.]Third Edition.Sebastopol O’Reilly Media Inc,2005.

[3]DANIELP.BOVET,MARCO CESATI,Understanding the Linux Kernels[M].[s.l.]Third Edition.Sebastopol O’Reilly Media Inc,2005.

[4]毛德操,胡希明.LINUX内核源代码情景分析[M].浙江大学出版社,2001.

USB设备驱动程序 篇7

关键词:WDM,USB接口,驱动程序

计算机发展速度飞快,传统的计算接口已经不能满足当前计算机高速发展的需求,键盘、鼠标、调制解调器、打印机、扫描仪、摄像头、数码相机、MP3随身听、外置硬盘、光驱设备往哪儿接呢?计算机业界迫切需要新的通用型、高速总线接口。

USB是一种应用在计算机领域的新型接口技术,它使得计算机周边设备连接标准化,具有安装方便、高带宽、易于扩展的特点。

本文利用Visual C++6.0、Driver Works以及Windows 2000 DDK开发包作为开发工具,采用WDM驱动程序模式,开发USB接口驱动程序,实现了USB键盘驱动程序的开发、安装及测试。

1 WDM驱动程序模型

在WDM驱动程序模型中,每个硬件设备包括两个驱动程序。一个驱动程序是硬件设备驱动程序,也称功能驱动程序,主要为用户提供适合的控制方式。它了解硬件工作的所有细节,负责初始化I/O操作,处理I/O操作完成时所带来的中断事件。通常由两个分离的执行文件组成。一个文件是类驱动程序,它了解如何处理操作系统使用的WDM协议,以及如何管理整个设备的基本特征。另一个文件称为微小驱动程序,它包含类驱动用于管理设备实例的厂商专有特征例程。类驱动程序和微小驱动程序合在一起才成为一个完整的功能驱动程序。

另一个驱动程序称为总线(BUS)驱动程序,负责管理硬件与计算机的连接。

一个完整的驱动程序包含许多例程,当操作系统遇到IRP时,它就调用驱动程序的例程来执行IRP的各种操作。

2 WDM驱动程序的结构

WDM驱动程序实行分层处理,被分成高层驱动程序、中间层驱动程序、底层驱动程序。每层驱动再把I/O请求划分成更简单的请求,以传给更下层的驱动执行。最底层的驱动程序在收到I/O请求后,通过硬件抽象层,与硬件进行交互,从而完成I/O请求工作。

WDM还引入了功能设备对象FDO(Functional Device Object)与物理设备对象PDO(Physical Device Object)两个新类来描述硬件。总线驱动程序(Bus Driver)位于最底层,控制对总线上所有设备的访问,并为每个设备创建一个PDO,功能驱动程序(Function Driver)管理FDO所代表的设备,过滤驱动程序(Filter Driver)用于监视和修改IRP流。

3 USB键盘驱动程序的开发

3.1 USB键盘驱动程序的实现和运行

用Driver Wizard3.0创建Usbkbd的WDM框架将自动生成一个工作区和两个工程,Test_Usbkbd files和Usbkbd files。其中Test_Usbkbd files是测试应用程序工程,Usbkbd files是驱动程序工程。

Test_Usbkbd files测试应用程序工程

OpenByIntf.cpp:OpenByIntf.cpp包含OpenByInterface函数,OpenByInterface函数用GUID接口方式与WDM进行通信。

Test_Usbkbd.cpp:是整个测试应用程序的主要文件,在这里添加相关代码,其作用是,打开设备的一个句柄,用于对设备进行读操作,并对DeviceIoControl函数进行调用, DeviceIoControl函数包含了对驱动程序的通信的命令。

Test_Usbkbd.cpp的文件结构

UsbkbdDriverInterface.h:定义设备接口的GUID。

Usbkbdioctl.h:定义驱动程序的控制代码。

Usbkbd.cpp:功能驱动程序,包含设备的初始化,DriverEntry例程和AddDevice历程。还重载了注册信息参数。

UsbkbdDevice.cpp:设备驱动程序,主要包括一些IRP的操作,如:清除(CleanUp(KIrp I))、关闭(Close(KIrp I))、创建(Create(KIrp I))、PnP管理(DefaultPnp(KIrp I))、电源管理(DefaultPower(KIrp I))、I/O控制(DeviceControl(KIrp I))、开始设备(OnStartDevice(KIrp I))、停止设备(OnStopDevice(KIrp I))、移除设备(OnRemoveDevice(KIrp I))、对设备进行读操作(Read(KIrp I))、系统控制(SystemControl(KIrp I))、通信控制(USBKBD_IOCTL_800_Handler(KIrp I))等。

在以上文件中添加代码。

function.h预定义相关的例程。

Usbkbd.h描述设备的相关信息,包括初始化时在注册表中的路径,注册表的参数,数据成员在 DriverEntry 期间被载入。

Usbkbdioctl.h为设备定义I/O控制命令。

Usbkbd.inf安装文件,在生成工程时自动生成。安装WDM设备驱动程序需要的所有必须的信息,包括要复制的文件列表、创建的注册表项等。

驱动程序通常使用DriverEntry作为驱动程序的默认入口点, 当PnP管理器发现一个硬件设备时,首先调用DriverEntry例程,DriverEntry例程是驱动程序初始化的入口点,它负责创建一个设备对象,定义其它的例程名称,设置例程的入口指针,从注册表中获取信息,初始化驱动程序,并初始化其它在驱动程序范围内的数据结构和资源。在DriverEntry中,主要的工作是在传递的驱动程序对象中存储一系列的回调例程指针。DRIVER_OBJECT结构由操作系统用于存储与驱动程序有关的任何信息。以后使用一个分开的结构存储每个设备的信息。Default Pnp(即插即用)主要是实现一个IRP_MJ_PNP处理程序。在驱动程序中,即插即用的基本处理包括:处理设备的添加和删除;得到分配的资源;处理查询停止和查询删除消息;处理停止设备消息;处理意外删除消息。Dispatch(分发例程)主要用来处理应用程序和驱动程序之间的通信,包括Great、Close、Cleanup、Read、Write、Control。分发例程是可选的,是为设备的硬件层编程服务的,通过该例程可以达到应用程序控制设备的目的。

WDM驱动程序通常由PnP管理器载入内存,然后调用它之中的AddDevice例程来创建设备。用一个inf安装文件来指明该驱动程序的一些参数。

一般情况下,DriverEntry例程要设置以下几个IRP处理函数:

DriverUnload 指向驱动程序的清除例程。I/O管理器会在卸载驱动程序前调用该例程。通常,WDM驱动程序的DriverEntry例程一般不分配任何资源,所以DriverUnload例程也没有什么清除工作要做。

DriverExtension→AddDevice 指向驱动程序的AddDevice函数。PnP管理器将为每个硬件实例调用一次AddDevice例程。这样将创建一个该设备对象。

DriverStartIo 如果驱动程序使用标准的IRP排队方式,应该设置该成员,使其指向驱动程序的StartIo例程。

MajorFunction 是一个指针数组,I/O管理器把每个数组元素都初始化成指向一个空函数,这个空函数仅返回失败。驱动程序可能仅需要处理几种类型的IRP,所以至少应该设置与那几种IRP类型相对应的指针元素,使它们指向相应的派遣函数。

3.2 功能驱动程序的相关步骤

用IoCreateDevice创建设备对象,并建立一个私有的设备扩展对象。

注册一个或多个设备接口,以便应用程序能够发现设备的存在。另外,还可以给出设备名并创建符号连接。

初始化设备扩展对象和设备对象的Flag成员。

调用IoAttachDeviceToDeviceStack函数,把新设备对象放到堆栈中。

Power例程。WDM驱动程序支持电源管理,电源管理器通过IRP指示驱动程序来改变电源状态,等待并响应系统唤醒事件和查询驱动程序设备,如果设备不支持电源管理,仅有一个默认的Power例程即可。

CreatFile:应用程序要想和设备进行通信,必须先打开设备,因此,应用程序用CreatFile函数来打开设备。

DeviceControl:应用程序可以调用DeviceIoControl函数与WDM驱动程序进行通信。DeviceIoControl函数分为同步调用和异步调用方式,采用同步方式时,应用程序调用DeviceIoControl函数将被阻塞,直到驱动程序完成响应的数据传输时才往下执行,因此这里采用异步调用方式,但是通常采用异步方式完成的驱动程序只允许一个应用程序,为了打开多个应用程序,应用程序调用并修改DeviceControl,使得每次只能有一个IRP处于等待中,这样可以打开多个应用程序。

ReadFile函数:应用程序和驱动程序进行通信的目的就是通过驱动程序对设备进行读、写、或控制等操作。在键盘驱动程序中,通过调用ReadFile函数,来读取键盘数据。

4 驱动程序的安装

用DriverWizard创建WDM框架程序之后,将自动生成一个工作区和两个工程文件。在相关文件添加相关代码后,将光标定位在Usbkbd file上,点击右键,选择“Set as Active Project”设置该工程为当前活动工程。然后点击编译,如果编译没有错的情况下,将会在sys文件夹下生成一些文件,包括一些自由构造和检查构造等文件,还生成一个objfre文件,生成的安装程序的系统文件Usbkbd.sys就包含在该文件里。

要安装上面生成的Usbkbd.sys文件,必须用驱动程序安装文件(inf)来安装。安装Usbkbd.sys文件有三种方法,但是在安装之前都要将sys文件下的Usbkbd.inf复制到“..sysobjferi386”目录下。因为Usbkbd.inf是在生成工作区时生成的,当时并没有sys文件,因此要将Usbkbd.inf复制到Usbkbd.sys所在目录下,Usbkbd.inf文件包含了安装WDM设备驱动程序需要的所有必须的信息,例如要复制的文件列表、创建的注册表项等。

从“控制面板”→“系统”→“硬件”→“添加硬件向导…”开始运行,按照向导一步一步找到Usbkbd.inf文件,完成该USB键盘驱动程序的安装。

驱动程序安装成功后将在设备管理器里可以看到安装的USBKBD设备的详细信息。如果驱动程序安装不上,可以用DriverStudio提供的Monitor跟踪测试。当驱动程序可以正常运行时,显示驱动程序的状态信息,当驱动程序不能运行时显示错误信息。

参考文献

[1]武安河.Windows2000/XP WDM设备驱动程序的开发[M].第2版.北京:电子工业出版社,2005.

[2]张惠娟,周利华,翟鸿鸣.Windows环境下的设备驱动程序设计[M].西安:西安电子科技大学出版社,2002.

USB设备驱动程序 篇8

关键词:嵌入式,USB,驱动程序

20世纪90年代中期,微机系统的应用日益广泛,需要连接的外部设备增加,而微机端口短缺,接口类型繁多。为解决这个问题,1997年,实用的USB1.1标准和计算机外部设备问世,1999年又出现了USB2.0规范,传输速率最高达到480 Mb/s,支持宽带数字摄像设备及新一代扫描仪、打印机和存储设备。该总线已经逐渐成为现代数据传输的发展趋势,被广泛地应用于PC机及嵌入式系统上。USB设备驱动程序主要负责利用系统提供的底层接口配置设备,与设备进行通讯。

1 WDM驱动程序的分层结构

WDM体系结构实行分层处理,即设备驱动被分成了若干层,典型的分层即高层驱动程序、中间层驱动程序、底层驱动程序。每层驱动再把I/O请求划分成更简单的请求,以传给更下层的驱动执行。最底层的驱动程序在收到I/O请求后,通过硬件抽象层,与硬件发生作用,从而完成I/O请求工作。在这样的架构下,上面的驱动层就不需要对每个操作系统都要开发。

2 USB驱动程序的WDM结构

USB客户驱动程序通过Windows系统提供的USB类驱动程序接口(USBDI)与下层驱动程序通信。在USB设备可用之前,必须对其进行配置和接口选择,然后所选择的接口的各个管道才是可用的。在USBDI的基础上进行编程将大大简化,用户不用关心IRP的类型,而只需要在相应的分发例程中通过构造USB块并将其通过USBDI发送下去,就可以实现对USB设备的控制。

3 USB驱动程序的设计举例

3.1 初始化模块

在初始化模块中,包括有每一个设备驱动程序都有的1个初始化入口点——Driver Entry例程,每次设备驱动程序启动时该例程被系统自动调用,其最重要的功能是设置驱动程序对应于I/O请求的主功能代码(Major Function)的回调例程。

初始化模块中还包括有Create和Close2个例程,这是Win32程序获得和释放设备句柄的唯一途径;Add Device例程在系统添加一个设备时被Pn P管理器调用,其主要工作是创建并初始化设备对象;Driver Unload例程在系统卸载硬件时使用,由I/O管理器调用,释放所有资源。

3.2 I/O模块

I/O模块由读写例程Read,Write和设备控制例程Io Control构成。

3.2.1 读写例程

读写2个例程用于实现批量数据传输。通过设置urb->Urb Bulk Or Interrupt Transfer.Transfer Flags标志位可以决定数据流向,因此,将它们放在同一个例程中。读写例程主要处理流程如下:

1)调用Io Get Current Irp Stack Location(),获得指向自身I/O堆栈单元的指针;

2)使用构造宏Usb Build Interrupt Or Bulk Transfer Request(),构造1个URB_BULK_OR_INTERR-UPT_TRANSFERURB类型的URB结构;

3)调用Io Get Nextlrp Stack Location()获得下一层驱动程序的I/O堆栈单元位置,并传递构造好的URB;

4)调用Io Set Completion Routine(),将1个I/O完成例程与IRP关联;

5)调用Io Call Driver(),将请求传递给下层驱动程序处理。

3.2.2 Io Control例程

用户程序使用Device Io Control函数传递一个称为I/O控制代码(IOCTL)的32位长度的参数,I/O管理器将IOCTL放在IRP的Parameters.Device IoControl.Io Control Code域中,在功能驱动程序中由Io Control例程使用该参数确定应执行的功能。

IOCTL值由CTL_CODE宏生成,CTL_CODE宏有4个宏参数。在本驱动程序中定义了2个IOCTL,分别用于复位管道和向USB固件发送一次批量传输字节数。Io Control例程对这两个IOCTL的处理流程与上面的读写例程类

4 结束语

上一篇:游戏美术场景下一篇:项目化教学国际贸易