📄 intpnp.c
字号:
/*++
Module Name:
intpnp.c
Abstract:
Plug and Play module.
This file contains routines to handle pnp requests.
These routines are not USB specific but is required
for every driver which conforms to the WDM model.
Environment:
Kernel mode
Notes:
--*/
#include "rtcapi.h"
#include "intusb.h"
#include "intpnp.h"
#include "intpwr.h"
#include "intdev.h"
#include "intrwr.h"
#include "intwmi.h"
#include "intusr.h"
#ifdef WIN98DRIVER
#include "intwdm98.h"
#endif
NTSTATUS
IntUsb_DispatchPnP(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these requests the driver will completely ignore.
In all cases it must pass on the IRP to the lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status value
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
KEVENT startDeviceEvent;
NTSTATUS ntStatus;
//
// initialize variables
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
deviceExtension = DeviceObject->DeviceExtension;
//
// since the device is removed, fail the Irp.
//
if(Removed == deviceExtension->DeviceState) {
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
KdPrint( ("///////////////////////////////////////////\n"));
KdPrint( ("IntUsb_DispatchPnP::"));
IntUsb_IoIncrement(deviceExtension);
if(irpStack->MinorFunction == IRP_MN_START_DEVICE) {
ASSERT(deviceExtension->IdleReqPend == 0);
}
else {
if(deviceExtension->SSEnable) {
CancelSelectSuspend(deviceExtension);
}
}
KdPrint( (PnPMinorFunctionString(irpStack->MinorFunction)));
switch(irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
ntStatus = HandleStartDevice(DeviceObject, Irp);
break;
case IRP_MN_QUERY_STOP_DEVICE:
//
// if we cannot stop the device, we fail the query stop irp
//
ntStatus = CanStopDevice(DeviceObject, Irp);
if(NT_SUCCESS(ntStatus)) {
ntStatus = HandleQueryStopDevice(DeviceObject, Irp);
return ntStatus;
}
break;
case IRP_MN_CANCEL_STOP_DEVICE:
ntStatus = HandleCancelStopDevice(DeviceObject, Irp);
break;
case IRP_MN_STOP_DEVICE:
ntStatus = HandleStopDevice(DeviceObject, Irp);
KdPrint( ("IntUsb_DispatchPnP::IRP_MN_STOP_DEVICE::"));
IntUsb_IoDecrement(deviceExtension);
return ntStatus;
case IRP_MN_QUERY_REMOVE_DEVICE:
//
// if we cannot remove the device, we fail the query remove irp
//
ntStatus = HandleQueryRemoveDevice(DeviceObject, Irp);
return ntStatus;
case IRP_MN_CANCEL_REMOVE_DEVICE:
ntStatus = HandleCancelRemoveDevice(DeviceObject, Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
ntStatus = HandleSurpriseRemoval(DeviceObject, Irp);
KdPrint( ("IntUsb_DispatchPnP::IRP_MN_SURPRISE_REMOVAL::"));
IntUsb_IoDecrement(deviceExtension);
return ntStatus;
case IRP_MN_REMOVE_DEVICE:
ntStatus = HandleRemoveDevice(DeviceObject, Irp);
return ntStatus;
case IRP_MN_QUERY_CAPABILITIES:
ntStatus = HandleQueryCapabilities(DeviceObject, Irp);
break;
default:
IoSkipCurrentIrpStackLocation(Irp);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
KdPrint( ("IntUsb_DispatchPnP::default::"));
IntUsb_IoDecrement(deviceExtension);
return ntStatus;
} // switch
//
// complete request
//
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// decrement count
//
KdPrint( ("IntUsb_DispatchPnP::"));
IntUsb_IoDecrement(deviceExtension);
return ntStatus;
}
NTSTATUS
HandleStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the dispatch routine for IRP_MN_START_DEVICE
Arguments:
DeviceObject - pointer to a device object.
Irp - I/O request packet
Return Value:
NT status value
--*/
{
KIRQL oldIrql;
KEVENT startDeviceEvent;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
LARGE_INTEGER dueTime;
KdPrint( ("HandleStartDevice - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
deviceExtension->UsbConfigurationDescriptor = NULL;
deviceExtension->UsbInterface = NULL;
deviceExtension->PipeContext = NULL;
//
// We cannot touch the device (send it any non pnp irps) until a
// start device has been passed down to the lower drivers.
// first pass the Irp down
//
KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
(PVOID)&startDeviceEvent,
TRUE,
TRUE,
TRUE);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
if(ntStatus == STATUS_PENDING) {
KeWaitForSingleObject(&startDeviceEvent,
Executive,
KernelMode,
FALSE,
NULL);
ntStatus = Irp->IoStatus.Status;
}
if(!NT_SUCCESS(ntStatus)) {
KdPrint( ("Lower drivers failed this Irp\n"));
return ntStatus;
}
//
// Read the device descriptor, configuration descriptor
// and select the interface descriptors
//
ntStatus = ReadandSelectDescriptors(DeviceObject);
if(!NT_SUCCESS(ntStatus)) {
KdPrint( ("ReadandSelectDescriptors failed\n"));
return ntStatus;
}
//
// enable the symbolic links for system components to open
// handles to the device
//
ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName,
TRUE);
if(!NT_SUCCESS(ntStatus)) {
KdPrint( ("IoSetDeviceInterfaceState:enable:failed\n"));
return ntStatus;
}
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(deviceExtension, Working);
deviceExtension->QueueState = AllowRequests;
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
//
// initialize wait wake outstanding flag to false.
// and issue a wait wake.
deviceExtension->FlagWWOutstanding = 0;
deviceExtension->FlagWWCancel = 0;
deviceExtension->WaitWakeIrp = NULL;
if(deviceExtension->WaitWakeEnable) {
IssueWaitWake(deviceExtension);
}
ProcessQueuedRequests(deviceExtension);
if(WinXpOrBetter == deviceExtension->WdmVersion) {
deviceExtension->SSEnable = deviceExtension->SSRegistryEnable;
//
// set timer.for selective suspend requests
//
if(deviceExtension->SSEnable) {
dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms
KeSetTimerEx(&deviceExtension->Timer,
dueTime,
IDLE_INTERVAL, // 5000 ms
&deviceExtension->DeferredProcCall);
deviceExtension->FreeIdleIrpCount = 0;
}
}
// If the device is powered up we may now
// start the Polling Interrupt URB.
if (deviceExtension->DevPower == PowerDeviceD0)
{
StartInterruptUrbIN((PDEVICE_EXTENSION) deviceExtension);
}
KdPrint( ("HandleStartDevice - ends\n"));
return ntStatus;
}
NTSTATUS
ReadandSelectDescriptors(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine configures the USB device.
In this routines we get the device descriptor,
the configuration descriptor and select the
configuration descriptor.
Arguments:
DeviceObject - pointer to a device object
Return Value:
NTSTATUS - NT status value.
--*/
{
PURB urb;
ULONG siz;
NTSTATUS ntStatus;
PUSB_DEVICE_DESCRIPTOR deviceDescriptor;
//
// initialize variables
//
urb = NULL;
deviceDescriptor = NULL;
//
// 1. Read the device descriptor
//
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if(urb) {
siz = sizeof(USB_DEVICE_DESCRIPTOR);
deviceDescriptor = ExAllocatePool(NonPagedPool, siz);
if(deviceDescriptor) {
UsbBuildGetDescriptorRequest(
urb,
(USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
deviceDescriptor,
NULL,
siz,
NULL);
ntStatus = CallUSBD(DeviceObject, urb);
if(NT_SUCCESS(ntStatus)) {
ASSERT(deviceDescriptor->bNumConfigurations);
ntStatus = ConfigureDevice(DeviceObject);
}
ExFreePool(urb);
ExFreePool(deviceDescriptor);
}
else {
KdPrint( ("Failed to allocate memory for deviceDescriptor"));
ExFreePool(urb);
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
else {
KdPrint( ("Failed to allocate memory for urb"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
NTSTATUS
ConfigureDevice(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This helper routine reads the configuration descriptor
for the device in couple of steps.
Arguments:
DeviceObject - pointer to a device object
Return Value:
NTSTATUS - NT status value
--*/
{
PURB urb;
ULONG siz;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
//
// initialize the variables
//
urb = NULL;
configurationDescriptor = NULL;
deviceExtension = DeviceObject->DeviceExtension;
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -