📄 sspnp.c
字号:
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
sSPnP.c
Abstract:
This file contains code to handle the pnp irps.
This is not USB specific but is essential for
every WDM driver.
Environment:
Kernel mode
Notes:
Copyright (c) 2000 Microsoft Corporation.
All Rights Reserved.
--*/
#include "selSusp.h"
#include "sSPnP.h"
#include "sSPwr.h"
#include "sSDevCtr.h"
#include "sSWmi.h"
#include "sSUsr.h"
NTSTATUS
SS_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 code
--*/
{
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;
}
SSDbgPrint(3, ("///////////////////////////////////////////\n"));
SSDbgPrint(3, ("SS_DispatchPnP::"));
SSIoIncrement(deviceExtension);
if(irpStack->MinorFunction == IRP_MN_START_DEVICE) {
ASSERT(deviceExtension->IdleReqPend == 0);
}
else {
if(deviceExtension->SSEnable) {
CancelSelectSuspend(deviceExtension);
}
}
SSDbgPrint(2, (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);
SSDbgPrint(3, ("SS_DispatchPnP::IRP_MN_STOP_DEVICE::"));
SSIoDecrement(deviceExtension);
return ntStatus;
case IRP_MN_QUERY_REMOVE_DEVICE:
//
// if we cannot remove the device, we fail the query remove irp
//
ntStatus = CanRemoveDevice(DeviceObject, Irp);
if(NT_SUCCESS(ntStatus)) {
ntStatus = HandleQueryRemoveDevice(DeviceObject, Irp);
return ntStatus;
}
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
ntStatus = HandleCancelRemoveDevice(DeviceObject, Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
ntStatus = HandleSurpriseRemoval(DeviceObject, Irp);
SSDbgPrint(3, ("SS_DispatchPnP::IRP_MN_SURPRISE_REMOVAL::"));
SSIoDecrement(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);
SSDbgPrint(3, ("SS_DispatchPnP::default::"));
SSIoDecrement(deviceExtension);
return ntStatus;
} // switch
//
// complete request
//
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// decrement count
//
SSDbgPrint(3, ("SS_DispatchPnP::"));
SSIoDecrement(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;
SSDbgPrint(3, ("HandleStartDevice - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// 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)) {
SSDbgPrint(1, ("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)) {
SSDbgPrint(1, ("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)) {
SSDbgPrint(1, ("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 variables
// and issue a wait wake.
deviceExtension->WaitWakeIrp = NULL;
deviceExtension->FlagWWCancel = 0;
deviceExtension->FlagWWOutstanding = 0;
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
SSDbgPrint(3, ("Setting the timer...\n"));
KeSetTimerEx(&deviceExtension->Timer,
dueTime,
IDLE_INTERVAL, // 5000 ms
&deviceExtension->DeferredProcCall);
deviceExtension->FreeIdleIrpCount = 0;
}
}
SSDbgPrint(3, ("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 {
SSDbgPrint(1, ("Failed to allocate memory for deviceDescriptor"));
ExFreePool(urb);
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
else {
SSDbgPrint(1, ("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;
//
// Read the first configuration descriptor
// This requires two steps:
// 1. Read the fixed sized configuration desciptor (CD)
// 2. Read the CD with all embedded interface and endpoint descriptors
//
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if(urb) {
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
if(configurationDescriptor) {
UsbBuildGetDescriptorRequest(
urb,
(USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
configurationDescriptor,
NULL,
sizeof(USB_CONFIGURATION_DESCRIPTOR),
NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -