WinXP下USB驱动开发(八)

3.3.2.8.    即插即用(PNP)

即插即用(Plug and Play -- PnP)管理器使用主功能码为IRP_MJ_PNPIRP与设备驱动程序交换信息和请求。这种类型的请求是新引入到Windows 2000WDM中的,在以前版本的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请求的第二个角色是指导驱动程序完成一系列状态转换。WORKINGSTOPPED是设备的两个基本状态。当你创建设备对象后,设备就立即进入STOPPED状态。WORKING状态指出设备是全部可操作的。此外,还有两个中间状态,PENDINGSTOPPENDINGREMOVE,它们出现在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_READIRP_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驱动由初始化、卸载、电源管理、WMIPNP等几大模块构成驱动结构。所有的模块在DriverEntry提供给体现,如表3-3-5.列出所有的功能模块。

3-3-5. 功能模块(IRPI/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驱动中,所有的操作都是围绕二级结构进行,以IRPI/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驱动开发(八))