WinXP下USB驱动开发(八)
来源:互联网 发布:mac apple store打不开 编辑:程序博客网 时间:2024/05/01 07:16
3.3.2.8. 即插即用(PNP)
即插即用(Plug and Play -- PnP)管理器使用主功能码为IRP_MJ_PNP的IRP与设备驱动程序交换信息和请求。这种类型的请求是新引入到Windows 2000和WDM中的,在以前版本的Windows NT中,大部分检测和配置设备的工作由设备驱动程序自己做。而WDM驱动程序可以让PnP管理器做这个工作。为了与PnP管理器协同工作,驱动程序开发者需要了解一些相关的IRP。
在WDM中,PnP请求扮演了两个角色。在第一个角色中,这些请求指示驱动程序何时以及如何配置或取消其硬件或自身的设置。表3-3-4列出了PnP请求可以指定的二十多个副功能码。其中有9个副功能码仅能由总线驱动程序处理,以星号标出;过滤器驱动程序或功能驱动程序仅下传这些IRP。剩下的副功能码中,有三个对过滤器驱动程序或功能驱动程序特别重要。PnP管理器使用IRP_MN_START_DEVICE来通知功能驱动程序其硬件被赋予了什么I/O资源,以及指导功能驱动程序做任何必要的硬件或软件设置以便设备能正常工作。IRP_MN_STOP_DEVICE告诉功能驱动程序关闭设备。IRP_MN_REMOVE_DEVICE告诉功能驱动程序关闭设备并释放与之关联的设备对象。
表3-3-4. IRP_MJ_PNP的副功能码 (*指出仅由总线驱动程序处理)
IRP副功能码
描述
IRP_MN_START_DEVICE
配置并初始化设备
IRP_MN_QUERY_REMOVE_DEVICE
设备可以被安全地删除吗?
IRP_MN_REMOVE_DEVICE
关闭并删除设备
IRP_MN_CANCEL_REMOVE_DEVICE
取消设备移除
IRP_MN_STOP_DEVICE
关闭设备
IRP_MN_QUERY_STOP_DEVICE
设备可以被安全地关闭吗?
IRP_MN_CANCEL_STOP_DEVICE
忽略以前的QUERY_STOP
IRP_MN_QUERY_DEVICE_RELATIONS
查询特定的设备列表
IRP_MN_QUERY_INTERFACE
获得直接调用函数地址
IRP_MN_QUERY_CAPABILITIES
取设备能力
IRP_MN_QUERY_RESOURCES*
取引导配置
IRP_MN_QUERY_RESOURCE_REQUIREMENTS*
取I/O资源需求
IRP_MN_QUERY_DEVICE_TEXT*
获得描述信息或位置串
IRP_MN_FILTER_RESOURCE_REQUIREMENTS
修改I/O资源需求列表
IRP_MN_READ_CONFIG*
读配置空间
IRP_MN_WRITE_CONFIG*
写配置空间
IRP_MN_EJECT*
弹出设备
IRP_MN_SET_LOCK*
设备弹出锁定/解除
IRP_MN_QUERY_ID*
取设备硬件ID
IRP_MN_QUERY_PNP_DEVICE_STATE
取设备状态
IRP_MN_QUERY_BUS_INFORMATION*
取父总线类型
IRP_MN_DEVICE_USAGE_NOTIFICATION
通知分页、dump、睡眠文件被创建或删除
IRP_MN_SURPRISE_REMOVAL
通知设备已经被删除
PnP请求的第二个角色是指导驱动程序完成一系列状态转换。WORKING和STOPPED是设备的两个基本状态。当你创建设备对象后,设备就立即进入STOPPED状态。WORKING状态指出设备是全部可操作的。此外,还有两个中间状态,PENDINGSTOP和PENDINGREMOVE,它们出现在WORKING状态前。SURPRISEREMOVED发生在物理硬件突然被移去的情况下。
3.3.2.9. USB读写
USB操作主要分读、写和I/O控制。正如前几小节中介绍USB信息流动是以包的方式进行。在USB的过程当中端点的包传输大小是有一定限制的,依据传输类型的不同而不同,如表3-3-4.所示。
表3-3-4. 包大小
传输类型
描述
纠错
包容量(字节)
延迟保证?
控制
用于发送和接收USB定义的结构化信息
是
少于或等于8,16,32,64
尽最大能力保证不延迟
批量
用于发送或接收小块无结构数据
是
少于或等于8,16,32,64
无
中断
与批量管道相似,但包括一个最大延迟
是
少于或等于64
以保证的最小速率轮询
等时
用于发送或接收有周期保证的大块无结构数据
否
少于或等于1023
每1毫秒帧中的固定部分
当读写数据存在限制的时候,我们开始要考虑大批量数据传输了。在大批量数据传输过程当中,我们必须将数据进行分段,即逐段进行发送,同时段大小最好和包大小一致。分段传输过程处理的时候,一般采用完成用例进行处理。通过完成例程,当一段数据发送完成之后返回STATUS_MORE_PROCESSING_REQUIRED使得驱动仍然使用该IRP继续发送数据,同时在完成例程函数中反复设置该完成例程,指导数据传输完毕,这种方式很像递归。
假设处理IRP_MJ_READ和IRP_MF_WRITE利用直接数据存储(deviceObject->Flags |= DO_DIRECT_IO)时,还需要定于_LPC2478_USB_RW_CONTEXT结构体,该结构体描述如下;
typedef struct _LPC2478_USB_RW_CONTEXT {
PURB Urb;
PMDL Mdl;
ULONG Length;
ULONG Numxfer;
ULONG_PTR VirtualAddress;
PDEVICE_EXTENSION DeviceExtension;
} LPC2478_USB_RW_CONTEXT, * PLPC2478_USB_RW_CONTEXT;
Ø Length域 MDL中剩余的长度。
Ø Numxfer域已经传输的数据量。
Ø VirtualAddress域数据保存地址。
有了这个结构体,已经可以帮助我们进行大批数据量传输,如图3-3-2-4设计的大批量数据读写算法。
3.3.2.10. 驱动结构
USB驱动由初始化、卸载、电源管理、WMI和PNP等几大模块构成驱动结构。所有的模块在DriverEntry提供给体现,如表3-3-5.列出所有的功能模块。
表3-3-5. 功能模块(IRP和I/O方式表示)
一级结构
二级结构
IRP_MJ_DEVICE_CONTROL
IOCTL_LPC2478_USB_RESET_PIPE
IOCTL_LPC2478_USB_GET_CONFIG_DESCRIPTOR
IOCTL_LPC2478_USB_RESET_DEVICE
IRP_MJ_POWER
IRP_MN_SET_POWER
IRP_MN_QUERY_POWER
IRP_MN_WAIT_WAKE
IRP_MN_POWER_SEQUENCE
IRP_MJ_PNP
IRP_MN_START_DEVICE
IRP_MN_QUERY_STOP_DEVICE
IRP_MN_CANCEL_STOP_DEVICE
IRP_MN_STOP_DEVICE
IRP_MN_QUERY_REMOVE_DEVICE
IRP_MN_CANCEL_REMOVE_DEVICE
IRP_MN_SURPRISE_REMOVAL
IRP_MN_REMOVE_DEVICE
IRP_MN_QUERY_CAPABILITIES
IRP_MJ_CREATE
IRP_MJ_CLOSE
IRP_MJ_CLEANUP
IRP_MJ_READ
IRP_MJ_WRITE
IRP_MJ_SYSTEM_CONTROL
QueryWmiRegInfo
QueryWmiDataBlock
SetWmiDataBlock
SetWmiDataItem
DriverUnload
DriverExtension->AddDevice
在整个USB驱动中,所有的操作都是围绕二级结构进行,以IRP和I/O方式显示驱动的结构再好不过。
3.3.3. 安装设计
Windows WDM模式驱动安装一般借助.INF文件进行,.INF是由段组成的,其中描述驱动的各种信息,有GUID、版本号、生产厂商等。把一个大的INF文件看成是一个树结构的线形描述可以更容易理解INF文件,如图3-3-4-0描述INF的文件结构。一个段就是树上的一个节点,而每个指令就是指向另一个段的指针。
在INF文件设计的时候,其中最重要的是找出设备标识符信息,这个信息标志着设备的存在且给出设备类型,如下图3-3-4-1获取设备的设备标识符信息。在图3-3-4-1中我们可以获取USB/VID0471&PID_2400/5&8897032&0&5,但是USB/VID0471&PID_2400才是我们所需要的。
获取设备标识符信息之后,开始可以设计INF文件信息,如下为设计后的INF文件内容。
; Installation inf for the ZLG EasyARM2400 USB Board
;
; (c) Copyright 2009 ZLG
;
[Version]
Signature="$CHICAGO$"
Class=USB
ClassGUID={36FC9E60-C465-11CF-8056-444553540000}
provider=%MSFT%
DriverVer=08/05/1999
[SourceDisksNames]
1="LPC2478USB Installation Disk",,,
[SourceDisksFiles]
LPC2400_USB.sys = 1
LPC2400_USB.inf = 1
[Manufacturer]
%MfgName%=ZLG
;设置设备标识符USB/VID_0471&PID_2400。
[ZLG]
%USB/VID_0471&PID_2400.DeviceDesc%=LPC2478USB.Dev, USB/VID_0471&PID_2400
;[PreCopySection]
;HKR,,NoSetupUI,,1
[DestinationDirs]
LPC2478USB.Files.Ext = 10,System32/Drivers
LPC2478USB.Files.Inf = 10,INF
[LPC2478USB.Dev]
CopyFiles= LPC2478USB.Files.Ext, LPC2478USB.Files.Inf
AddReg= LPC2478USB.AddReg
[LPC2478USB.Dev.NT]
CopyFiles= LPC2478USB.Files.Ext, LPC2478USB.Files.Inf
AddReg= LPC2478USB.AddReg
[LPC2478USB.Dev.NT.Services]
Addservice = LPC2478USB, 0x00000002, BULKUSB.AddService
[LPC2478USB.AddService]
DisplayName = % LPC2478USB.SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%/System32/Drivers/LPC2400_USB.sys
LoadOrderGroup = Base
[LPC2478USB.AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,LPC2400_USB.sys
HKLM,"System/Currentcontrolset/Services/LPC2478USB /Parameters","MaximumTransferSize",0x10001,4096
HKLM,"System/Currentcontrolset/Services/LPC2478USB /Parameters","DebugLevel",0x10001,2
HKLM,"System/Currentcontrolset/services/LPC2478USB /Parameters","BulkUsbEnable",0x10001,1
[LPC2478USB.Files.Ext]
LPC2400_USB.sys
[LPC2478USB.Files.Inf]
LPC2400_USB.inf
;---------------------------------------------------------------;
[Strings]
MSFT="ZLG"
MfgName="NXP"
USB/VID_0471&PID_2400.DeviceDesc="ZLG EasyARM2400 USB Device"
BULKUSB.SvcDesc="LPC2400_USB.sys EasyARM2400 USB Bulk IO driver"
Ø INF文件开始于一个Version段,该段确定文件中描述的设备类型。
Ø SourceDisksFiles段指出安装程序可以在1号盘上找到PKTDMA.SYS文件。
Ø SourceDisksNames段指出磁盘1有一个人类可读的标签“LPC2478USB Installation Disk”并包含一个名为disk1的文件,用于安装程序寻找并检验驱动器中是否有正确的磁盘。注意这两个段名中有一个容易忘记的字母“s”。
Ø DestinationDirs段指出文件复制操作的目标路径。DefaultDestDir是未指定目标目录文件的默认目标路径。你可以用一个数值代码来指定目标路径,这个代码的完整列表见DDK文档,经常使用的仅有如下几个:
n 目录“10”为Windows目录(例如“/Windows”或“/Winnt”)。
n 目录“11”是System目录(例如,“/Windows/System”或“/Winnt/System32”)。
n 目录“12”是Drivers目录,指在Windows 2000系统中(例如,“/Winnt/System32/Drivers”)。但在Windows 98中这个数值有不同的含义(例如“/Windows/System/Iosubsys”)。
WDM驱动程序存在于Driver目录中。如果你的CopyFiles段仅用于向Windows 2000安装,那么仅指定目录数值12就可以了。如果你还想使该段能向Windows 98中安装,我推荐你用“10,System32/Drivers”,它以两种方式标识Driver目录。
Ø 有时候我们需要为PnP管理器做些安排,以使它知道应该载入哪个文件。段.Services用于实现这个目标。
Ø BULKUSB.AddReg段通过内核的方式,向相关注册表中创建或则写入参数以供驱动采用。
- WinXP下USB驱动开发(八)
- WinXP下USB驱动开发(一)
- WinXP下USB驱动开发(二)
- WinXP下USB驱动开发(三)
- WinXP下USB驱动开发(四)
- WinXP下USB驱动开发(五)
- WinXP下USB驱动开发(六)
- WinXP下USB驱动开发(七)
- WinXP下USB驱动开发(九)
- WinXP下USB驱动开发(十)
- linux下USB驱动开发
- linux下USB驱动开发
- linux下USB驱动开发
- WinXP下 VC6.0 驱动开发环境配置
- windows下驱动开发配置(win10,win7,winXP)
- Linux USB RNDIS设备在WinXP、Win7、Win10下的驱动安装
- Linux系统下USB摄像头驱动开发
- Linux系统下USB摄像头驱动开发
- ctags的使用
- .NET环境下Email的技术介绍
- 随机数组——不重复下标的一种思路
- 玛雅人的故乡
- Oracle 数据类型
- WinXP下USB驱动开发(八)
- PL/SQL Developer 中文乱码解决
- ASP.NET 2.0中发送电子邮件剖析之一
- 网友酷帖:深圳关内关外生活对比(2009-6-9)
- (0x80040E07) 标准表达式中数据类型不匹配。
- 观点,学历的价值
- 网友酷帖:深圳关内关外生活对比(2009-6-9)
- ASP.NET 2.0发送电子邮件全面剖析之二
- XmlSerializer学习