class KUsbLowerDevice
【Overview】
KUsbLowerDevice类是实现一个USB客户端驱动的核心类。它使驱动能够控制一个USB设备的默认控制管道(the default control pipe),能够配置设备,并且能够向设备传递各种控制请求和状态请求。这个类相当于USB协议栈的逻辑设备层(logical device layer),为USB和设备端点(device endpoints)之间的路由通信负责。
KUsbLowerDevice类是KPnpLowerDevice类的子类,因此继承了它的成员函数。这个基类提供了对底层物理设备属性的控制。
一个KUsbLowerDevice类实例(或者是它的子类)就象征着endpoint 0(控制管道the control pipe)。所以你不用为endpoint 0实例化一个KUsbPipe类。
当系统检测到一个USB设备,它会创建一个设备对象来表示系统中的这个物理设备。这个设备对象被称为物理设备对象(PDO)。系统决定了为设备负责的驱动程序,并且调用那个驱动的AddDevice 入口函数,传递一个指向PDO的指针作为参数。
一般来说,AddDevice 创建一个功能设备对象(FDO),就相当于传进来的PDO。FDO的角色只是使应用程序和更高层的驱动程序能够通过客户端驱动发送IO请求(I/O requests)。FDO是一个KPnpDevice派生类的实例。
要创建FDO和PDO之间的连接(biding),FDO嵌入一个KUsbLowerDevice类型的数据成员。在construction 函数或者Initialize函数中,FDO和PDO联系起来,因此FDO把自己插入驱动程序栈里并开始为PDO操作IRPs(IO请求包I/O request packets)。
对于怎样使用KUsbLowerDevice的成员函数进行USB设备的配置,参见下面的【Configuring a USB Device】部分,这在DriverWorks里是以链接方式给出的一个专题。
【Configuring a USB Device】
下面是构造一个能够控制USB设备的驱动程序的几个要点说明(keys):
(1)USB驱动必须是WDM驱动程序。这意味着你在继承KDriver的类里需要一个AddDevice函数。你的function.h文件必须有宏定义#define DRIVER_FUNCTION_ADD_DEVICE,DRIVER_FUNCTION_PNP和DRIVER_FUNCTION_POWER。
(2)USB设备通常是支持即插即用的。从KPnpDevice派生一个类。这个类必须有一个KUsbLowerDevice类型的数据成员。而且对于每种配置的每个接口,都要声明一个KUsbInterface类型的数据成员。对每个USB端点(endpoint),要声明一个KUsbPipe类型的数据成员。
(3)你的设备类必须重写,至少重写OnStartDevice 和 OnStopDevice函数。可能还有其他你需要重写的成员函数,但是系统需要的很多PnP(即插即用)和Power(电源管理)功能是由它的基类KPnpDevice实现了的。
(4)在设备构造函数里,你必须首先通过调用KUsbLowerDevice类的Initialize函数对它进行初始化。然后调用每个KUsbInterface类的Initialize对它们分别进行初始化。要保证调用这些函数的新形式(new forms)。遗留的形式之所以存在仅仅是为了保持对老式设备驱动的兼容。然后调用SetLowerDevice, SetPnpPolicy和SetPowerPolicy三个函数。
(5)在你的设备类的OnStartDevice函数里,调用KUsbLowerDevice::ActivateConfiguration来配置设备。这个函数将建立KUsbPipe、KUsbInterface对象和当前USB管道(pipes)、接口之间的联系(biding)。
(6)在OnStopDevice函数里,调用KUsbLowerDevice::DeActivateConfiguration函数。
具体请参考安装目录../DriverWorks/examples/wdm下的示例程序USBTHERM,或者使用DriverWizard生成一个定制的USB客户端驱动程序。
【Member Functions】
1、KUsbLowerDevice - Constructor (2 forms)构造函数。运行于PASSIVE_LEVEL中断级别上。
FORM 1:
KUsbLowerDevice(
KDevice* AttachingDevice,
PDEVICE_OBJECT PhysicalDeviceObject,
NTSTATUS* pStatus
);
FORM 2:
KUsbLowerDevice(void);
FORM 3:
KUsbLowerDevice(
PDEVICE_OBJECT TopOfStackDevice,
PDEVICE_OBJECT PhysicalDeviceObject,
NTSTATUS* pStatus
);
如果用Form2,就必须提前调用Initialize函数。
2、Initialize - Initialization初始化一个类实例,只有使用默认构造函数(不带参数)进行构造时用这个函数初始化。运行于PASSIVE_LEVEL中断级别上。
FORM 1:
NTSTATUS Initialize(
KDevice* AttachingDevice,
PDEVICE_OBJECT PhysicalDeviceObject
);
FORM 2:
NTSTATUS Initialize(
PDEVICE_OBJECT TopOfStackDeviceObject,
PDEVICE_OBJECT PhysicalDeviceObject
);
3、GetDeviceDescriptor - Retrieve device descriptor从设备取得设备描述符,这个函数和SubmitUrb函数同步调用。运行于PASSIVE_LEVEL中断级别上。
函数原型:
NTSTATUS GetDeviceDescriptor( PUSB_DEVICE_DESCRIPTOR pDevDesc );
设备描述符的数据结构定义:
typedef struct _USB_DEVICE_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdUSB;
UCHAR bDeviceClass;
UCHAR bDeviceSubClass;
UCHAR bDeviceProtocol;
UCHAR bMaxPacketSize0;
USHORT idVendor;
USHORT idProduct;
USHORT bcdDevice;
UCHAR iManufacturer;
UCHAR iProduct;
UCHAR iSerialNumber;
UCHAR bNumConfigurations;
} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
4、GetStringDescriptor - Retrieve string descriptor获取一个串描述符。运行于PASSIVE_LEVEL中断级别上。
函数原型:
NTSTATUS GetStringDescriptor(
UCHAR Index,
PSTR pStr,
LONG MaxLen,
SHORT LangId
);
串描述符数据结构定义:
typedef struct _USB_STRING_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
WCHAR bString[1];
} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR;
5、GetCurrentFrameNumber - Retrieves the current USB frame number from the system USB bus driver从系统的USB总线驱动获得当前USB驱动程序的USB帧编号。
函数原型:
ULONG GetCurrentFrameNumber( VOID);
6、ActivateConfiguration - Activate a particular configuration of the device激活指定的配置。FORM1打开驱动中实例化的KUsbInterface和KUsbPipe对象。当对象已经打开时,函数也会向这个对象所抽象的设备上的端点(endpoint)或接口(interface)提交请求。
FORM 1: (Preferred推荐)
AC_STATUS ActivateConfiguration(
USHAR ConfigurationValue,
ULONG MaxConfigSize=1024
);
FORM 2: (Legacy保留,不推荐)
AC_STATUS ActivateConfiguration(
UCHAR ConfigurationValue,
ULONG nEndpointsDescribed,
USB_ENDPOINT* Endpoints,
USB_ENDPOINT** ppProblem=NULL,
ULONG MaxConfigSize=1024
);
7、DeActivateConfiguration - Set the device to the unconfigured state. (Works like UnConfigure, but also cleans up internal objects.)通知USB总线驱动程序将设备置于非配置状态,关闭ActivateConfiguration打开的KUsbInterface和KUsbPipe对象。这个函数只有当ActivateConfiguration 使用FORM1时使用,FORM2时没有相应的De-函数。运行于PASSIVE_LEVEL中断级别上。
函数原型:
NTSTATUS DeActivateConfiguration(
PIO_COMPLETION_ROUTINE pfnCompletionRoutine=NULL,
PVOID pContext=NULL
);
8、Preconfigure - Prepare for configuration by retrieving a configuration descriptor.获取一个配置描述符。配置一个USB设备的第一步。如果调用成功(返回STATUS_SUCCESS),就可以使用m_config数据成员进行配置描述符的存取了。运行于PASSIVE_LEVEL中断级别上。
函数原型:
NTSTATUS Preconfigure(
UCHAR ConfigIndex=0,
ULONG MaxConfigSize=DEFAULT_CONFIG_SIZE
);
9、LocateInterface - Retrieve a pointer to a qualified interface descriptor.在当前已指定特征的配置描述符中找到一个接口。返回这个接口描述符的指针,没找到的话就返回NULL。调用者必须处于IRQL < DISPATCH_LEVEL中断级别上。
函数原型:
PUSB_INTERFACE_DESCRIPTOR LocateInterface(
PVOID* pStart,
PUSB_ENDPOINT_DESCRIPTOR* ppEndpoints,
LONG InterfaceNumber = -1,
LONG AlternateSetting = -1,
LONG InterfaceClass = -1,
LONG InterfaceSubClass = -1,
LONG InterfaceProtocol = -1
);
10、PreconfigureInterface - Add a specified interface to the set to be configured.设置一个接口和相关的管道等待被配置。调用Preconfigure函数后,驱动为每个接口调用这个函数,简单的存储信息直到Configure函数被调用(Configure用来设置配置信息)。
函数原型:
NTSTATUS PreconfigureInterface( PUSB_INTERFACE_DESCRIPTOR pInterfaceDesc );
11、Configure - Set the current configuration.设置物理设备的当前配置信息。调用者处于IRQL < DISPATCH_LEVEL中断级别上。
函数原型:
NTSTATUS Configure(void);
12、Unconfigure - Unconfigure the device将设备置为未配置状态(unconfigured state)。调用者处于PASSIVE_LEVEL中断级别上。
函数原型:
NTSTATUS Unconfigure(
PIO_COMPLETION_ROUTINE CompletionRoutine=NULL,
PVOID Context=NULL
);
13、GetStatus - Get the device status获得设备状态。运行于PASSIVE_LEVEL中断级别上。
函数原型:
NTSTATUS GetStatus(
PUSHORT pStatus,
PIO_COMPLETION_ROUTINE CompletionRoutine=NULL,
PVOID Context=NULL
);
14、SetFeature - Set a device feature设置(使能)一个设备特性,申请URB失败的话返回STATUS_INSUFFICIENT_RESOURCES。运行于PASSIVE_LEVEL中断级别上。
函数原型:
NTSTATUS SetFeature(
USHORT Feature,
PIO_COMPLETION_ROUTINE CompletionRoutine=NULL,
PVOID Context=NULL
);
15、ClearFeature - Clear a device feature清除一个设备特征,申请URB失败的话返回STATUS_INSUFFICIENT_RESOURCES。运行于PASSIVE_LEVEL中断级别上。
函数原型:
NTSTATUS ClearFeature(
USHORT Feature,
PIO_COMPLETION_ROUTINE CompletionRoutine=NULL,
PVOID Context=NULL
);
16、BuildClassRequest - Build an URB for a class request为类请求构造一个URB,申请内存(非分页内存),并/或 为逻辑设备初始化一个_URB_CONTROL_VENDOR_OR_CLASS_REQUEST结构。调用者处于IRQL <= DISPATCH_LEVEL中断级别上。
FORM 1:
PURB BuildClassRequest(
PUCHAR TransferBuffer,
ULONG TransferBufferLength,
UCHAR RequestTypeReservedBits,
UCHAR Request,
USHORT Value,
BOOLEAN bIn=FALSE,
BOOLEAN bShortOk=FALSE,
PURB Link=NULL,
UCHAR Index=0,
USHORT Function=URB_FUNCTION_CLASS_DEVICE,
PURB pUrb=NULL
);
FORM 2:
PURB BuildClassRequest(
KMemory& TransferBufferMDL,
ULONG TransferBufferLength,
UCHAR RequestTypeReservedBits,
UCHAR Request,
USHORT Value,
BOOLEAN bIn=FALSE,
BOOLEAN bShortOk=FALSE,
PURB Link=NULL,
UCHAR Index=0,
USHORT Function=URB_FUNCTION_CLASS_DEVICE,
PURB pUrb=NULL
);
17、BuildVendorRequest - Build an URB for a vendor request为供应商请求构造一个URB,申请内存(非分页内存),并/或 为逻辑设备初始化一个_URB_CONTROL_VENDOR_OR_CLASS_REQUEST结构。调用者处于IRQL <= DISPATCH_LEVEL中断级别上。
PURB BuildVendorRequest(
PUCHAR TransferBuffer,
ULONG TransferBufferLength,
UCHAR RequestTypeReservedBits,
UCHAR Request,
USHORT Value,
BOOLEAN bIn=FALSE,
BOOLEAN bShortOk=FALSE,
PURB Link=NULL
UCHAR Index=0,
USHORT Function=URB_FUNCTION_VENDOR_DEVICE,
PURB pUrb=NULL
);
FORM 2:
PURB BuildVendorRequest(
KMemory& TransferBufferMDL,
ULONG TransferBufferLength,
UCHAR RequestTypeReservedBits,
UCHAR Request,
USHORT Value,
BOOLEAN bIn=FALSE,
BOOLEAN bShortOk=FALSE,
PURB Link=NULL
UCHAR Index=0,
USHORT Function=URB_FUNCTION_VENDOR_DEVICE
PURB pUrb=NULL
);
18、ReleaseResources - Releases all of the dynamic resources for the object释放所有的动态资源。
函数原型:
void ReleaseResources(void);
19、SubmitUrb - Submits an URB (USB Request Block) to the system USB bus driver for processing提交一个URB(USB Request Block)给系统USB总线驱动程序去处理。调用者处于IRQL <= DISPATCH_LEVEL中断级别上。
FORM 1:
NTSTATUS SubmitUrb(
PURB pUrb,
PIO_COMPLETION_ROUTINE CompletionRoutine=NULL,
PVOID CompletionContext=NULL,
ULONG mSecTimeOut=0
);
FORM 2:
NTSTATUS SubmitUrb(
KIrp I,
PURB pUrb,
PIO_COMPLETION_ROUTINE CompletionRoutine=NULL,
PVOID CompletionContext=NULL,
ULONG mSecTimeOut=0
);
----------------
§ 译自"DriverWorks帮助文件" §
§ 李文凯 2008年04月28日 §
----------------