📄 mavpnp.c
字号:
//****************************************************************************
//
// MAVPNP.C - Routines to handle Plug-N-Play IRPs.
//
// Copyright (c) 2000 Cirrus Logic, Inc.
// Copyright (c) 1997-1998 Microsoft Corporation. All Rights Reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
//****************************************************************************
#include "wdm.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "mavusb.h"
#include "mavproto.h"
//****************************************************************************
//
// Dispatch table routine for IRP_MJ_PNP. Process the Plug and Play IRPs sent
// to this device.
//
// Arguments:
//
// DeviceObject - pointer to our FDO (Functional Device Object)
//
// Irp - pointer to an I/O Request Packet
//
// Return Value:
//
// NT status code
//
//****************************************************************************
NTSTATUS
MavUsb_ProcessPnPIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT stackDeviceObject;
KEVENT startDeviceEvent;
//
// Get a pointer to the device extension.
//
deviceExtension = DeviceObject->DeviceExtension;
//
// Get a pointer to the current location in the IRP stack. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
//
// Get a pointer to the PDO.
//
stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
//
// Increment the count of pending IRPs.
//
MavUsb_IncrementIoCount(DeviceObject);
//
// Determine what to do based on the minor function in the IRP.
//
switch(irpStack->MinorFunction)
{
//
// The PnP Manager sends this IRP after it has assigned resources, if
// any, to the device. The device may have been recently enumerated
// and is being started for the first time, or the device may be
// restarting after being stopped for resource reconfiguration.
//
case IRP_MN_START_DEVICE:
{
//
// Initialize an event we can wait on for the PDO to be done with
// this IRP.
//
KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// Set a completion routine so it can signal our event when the PDO
// is done with the IRP.
//
IoSetCompletionRoutine(Irp, MavUsb_IrpCompletionRoutine,
&startDeviceEvent, TRUE, TRUE, TRUE);
//
// Pass the IRP to the PDO.
//
ntStatus = IoCallDriver(stackDeviceObject, Irp);
//
// If PDO is not done yet, wait for the event to be set in our
// completion routine.
//
if(ntStatus == STATUS_PENDING)
{
//
// Wait for IRP to complete.
//
KeWaitForSingleObject(&startDeviceEvent, Suspended, KernelMode,
FALSE, NULL);
//
// Get the status from the IRP.
//
ntStatus = Irp->IoStatus.Status;
}
//
// See if the PDO successfully handled the IRP.
//
if(NT_SUCCESS(ntStatus))
{
//
// Now we're ready to do our own startup processing. USB
// client drivers such as us set up URBs (USB Request Packets)
// to send requests to the host controller driver (HCD). The
// URB structure defines a format for all possible commands
// that can be sent to a USB device. Here, we request the
// device descriptor and store it, and configure the device.
//
ntStatus = MavUsb_StartDevice(DeviceObject);
//
// Set the status in the IRP.
//
Irp->IoStatus.Status = ntStatus;
}
//
// Complete the IRP.
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// Decrement the count of pending requests.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// Return the result.
//
return(ntStatus);
}
//
// The IRP_MN_QUERY_STOP_DEVICE/IRP_MN_STOP_DEVICE sequence only occurs
// during "polite" shutdowns, such as the user explicitily requesting
// the service be stopped in, or requesting unplug from the PnP tray
// icon. This sequence is NOT received during "impolite" shutdowns,
// such as someone suddenly yanking the USB cord or otherwise
// unexpectedly disabling/resetting the device.
//
// If a driver sets STATUS_SUCCESS for this IRP, the driver must not
// start any operations on the device that would prevent that driver
// from successfully completing an IRP_MN_STOP_DEVICE for the device.
//
// For mass storage devices such as disk drives, while the device is in
// the stop-pending state, the driver holds IRPs that require access to
// the device, but for most USB devices, there is no 'persistent
// storage', so we will just refuse any more IO until restarted or the
// stop is cancelled.
//
// If a driver in the device stack determines that the device cannot be
// stopped for resource reconfiguration, the driver is not required to
// pass the IRP down the device stack. If a query-stop IRP fails, the
// PnP Manager sends an IRP_MN_CANCEL_STOP_DEVICE to the device stack,
// notifying the drivers for the device that the query has been
// cancelled and that the device will not be stopped.
//
case IRP_MN_QUERY_STOP_DEVICE:
{
//
// It is possible to receive this IRP when the device has not been
// started (as on a boot device).
//
if(!deviceExtension->DeviceStarted)
{
//
// If we've never been started, just pass it on.
//
IoSkipCurrentIrpStackLocation(Irp);
ntStatus =
IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// Return the status.
//
return(ntStatus);
}
//
// Fail the request if we have any read/write IRPs pending.
//
if(deviceExtension->StagedIoPending)
{
ntStatus = STATUS_UNSUCCESSFUL;
}
else
{
//
// We'll not veto it; pass it on and flag that stop was
// requested. Once StopDeviceRequested is set no new IOCTL or
// read/write IRPs will be passed down the stack to lower
// drivers; all will be quickly failed.
//
deviceExtension->StopDeviceRequested = TRUE;
//
// Set the IRP status to success.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
}
//
// We're done with this IRP.
//
break;
}
//
// The PnP Manager uses this IRP to inform the drivers for a device
// that the device will not be stopped for resource reconfiguration.
// This should only be received after a successful
// IRP_MN_QUERY_STOP_DEVICE.
//
case IRP_MN_CANCEL_STOP_DEVICE:
{
//
// It is possible to receive this IRP when the device has not been
// started.
//
if(!deviceExtension->DeviceStarted)
{
//
// If we've never been started, just pass it on.
//
IoSkipCurrentIrpStackLocation(Irp);
ntStatus =
IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// Return the status.
//
return(ntStatus);
}
//
// Reset this flag so new IOCTL and IO IRP processing will be
// re-enabled.
//
deviceExtension->StopDeviceRequested = FALSE;
//
// Set the IRP status to success.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// We're done with this IRP.
//
break;
}
//
// The PnP Manager sends this IRP to stop a device so it can
// reconfigure its hardware resources. The PnP Manager only sends this
// IRP if a prior IRP_MN_QUERY_STOP_DEVICE completed successfully.
//
case IRP_MN_STOP_DEVICE:
{
//
// Send the select configuration urb with a NULL pointer for the
// configuration handle. This closes the configuration and puts
// the device in the 'unconfigured' state.
//
ntStatus = MavUsb_StopDevice(DeviceObject);
//
// Set the status in the IRP.
//
Irp->IoStatus.Status = ntStatus;
//
// We're done with this IRP.
//
break;
}
//
// In response to this IRP, drivers indicate whether the device can be
// removed without disrupting the system.
//
// If a driver determines it is safe to remove the device, the driver
// completes any outstanding I/O requests, arranges to hold any
// subsequent read/write requests, and sets Irp->IoStatus.Status to
// STATUS_SUCCESS. Function and filter drivers then pass the IRP to
// the next-lower driver in the device stack. The underlying bus
// driver calls IoCompleteRequest.
//
// If a driver sets STATUS_SUCCESS for this IRP, the driver must not
// start any operations on the device that would prevent that driver
// from successfully completing an IRP_MN_REMOVE_DEVICE for the device.
// If a driver in the device stack determines that the device cannot be
// removed, the driver is not required to pass the query-remove IRP
// down the device stack. If a query-remove IRP fails, the PnP Manager
// sends an IRP_MN_CANCEL_REMOVE_DEVICE to the device stack, notifying
// the drivers for the device that the query has been cancelled and
// that the device will not be removed.
//
case IRP_MN_QUERY_REMOVE_DEVICE:
{
//
// It is possible to receive this IRP when the device has not been
// started.
//
if(!deviceExtension->DeviceStarted)
{
//
// If we've never been started, just pass it on.
//
IoSkipCurrentIrpStackLocation(Irp);
ntStatus =
IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// Return the status.
//
return(ntStatus);
}
//
// Once RemoveDeviceRequested is set no new IOCTL or read/write
// IRPs will be passed down the stack to lower drivers; all will be
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -