?? pnp.c
字號:
/*++
Copyright (c) 2005-2006 E0 Technology,Inc.
Module Name:
pnp.c
Abstract:
Virtual Com Port Driver for USB to RS232 Converter of E0 Technology,Inc.
Environment:
Kernel mode
Notes:
Revision History:
2006/3/1 : Adapted from the BulkUsb DDK sample.
--*/
#include "usb2com.h"
NTSTATUS
USB2COM_ProcessPnPIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
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
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
NTSTATUS waitStatus;
PDEVICE_OBJECT stackDeviceObject;
KEVENT startDeviceEvent;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get a pointer to the device extension
//
deviceExtension = DeviceObject->DeviceExtension;
stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
USB2COM_KdPrint( DBGLVL_MEDIUM, ( "enter USB2COM_ProcessPnPIrp() IRP_MJ_PNP, minor %s\n",
USB2COM_StringForPnpMnFunc( irpStack->MinorFunction ) ));
// inc the FDO device extension's pending IO count for this Irp
USB2COM_IncrementIoCount(DeviceObject);
USB2COM_ASSERT( IRP_MJ_PNP == irpStack->MajorFunction );
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
// 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.
// 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,
USB2COM_IrpCompletionRoutine,
&startDeviceEvent, // pass the event to the completion routine as the Context
TRUE, // invoke on success
TRUE, // invoke on error
TRUE); // invoke on cancellation
// let the PDO process the IRP
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
waitStatus = KeWaitForSingleObject(
&startDeviceEvent,
Suspended,
KernelMode,
FALSE,
NULL);
ntStatus = Irp->IoStatus.Status;
}
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 = USB2COM_StartDevice(DeviceObject);
Irp->IoStatus.Status = ntStatus;
}
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
USB2COM_DecrementIoCount(DeviceObject);
return ntStatus; // end, case IRP_MN_START_DEVICE
case IRP_MN_QUERY_STOP_DEVICE:
// 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.
// It is possible to receive this irp when the device has not been started
// ( as on a boot device )
if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
USB2COM_KdPrint( DBGLVL_MEDIUM,("USB2COM_ProcessPnPIrp() IRP_MN_QUERY_STOP_DEVICE when device not started\n"));
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
USB2COM_DecrementIoCount(DeviceObject);
return ntStatus;
}
// fail the request if we have any read/write IRPS pending
if( deviceExtension->StagedPendingIrpCount ) {
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;
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break; // end, case IRP_MN_QUERY_STOP_DEVICE
case IRP_MN_CANCEL_STOP_DEVICE:
// 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.
// It is possible to receive this irp when the device has not been started
if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
USB2COM_KdPrint( DBGLVL_MEDIUM,("USB2COM_ProcessPnPIrp() IRP_MN_CANCEL_STOP_DEVICE when device not started\n"));
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
USB2COM_DecrementIoCount(DeviceObject);
return ntStatus;
}
// Reset this flag so new IOCTL and IO Irp processing will be re-enabled
deviceExtension->StopDeviceRequested = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break; // end, case IRP_MN_CANCEL_STOP_DEVICE
case IRP_MN_STOP_DEVICE:
// 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.
// Cancel any pending io requests. (there shouldn't be any)
USB2COM_CancelPendingIo( DeviceObject );
//
// 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 = USB2COM_StopDevice(DeviceObject);
Irp->IoStatus.Status = ntStatus;
break; // end, case IRP_MN_STOP_DEVICE
case IRP_MN_QUERY_REMOVE_DEVICE:
// 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.
// It is possible to receive this irp when the device has not been started
if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
USB2COM_KdPrint( DBGLVL_MEDIUM,("USB2COM_ProcessPnPIrp() IRP_MN_QUERY_STOP_DEVICE when device not started\n"));
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
USB2COM_DecrementIoCount(DeviceObject);
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 quickly failed
deviceExtension->RemoveDeviceRequested = TRUE;
// Wait for any io request pending in our driver to
// complete before returning success.
// This event is set when deviceExtension->PendingIoCount goes to 1
// match the inc at the begining of the dispatch routine
USB2COM_DecrementIoCount(DeviceObject);
waitStatus = KeWaitForSingleObject(
&deviceExtension->NoPendingIoEvent,
Suspended,
KernelMode,
FALSE,
NULL);
USB2COM_IncrementIoCount(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
break; // end, case IRP_MN_QUERY_REMOVE_DEVICE
case IRP_MN_CANCEL_REMOVE_DEVICE:
// The PnP Manager uses this IRP to inform the drivers
// for a device that the device will not be removed.
// It is sent only after a successful IRP_MN_QUERY_REMOVE_DEVICE.
if (!deviceExtension->DeviceStarted) { // if get when never started, just pass on
USB2COM_KdPrint( DBGLVL_MEDIUM,("USB2COM_ProcessPnPIrp() IRP_MN_CANCEL_REMOVE_DEVICE when device not started\n"));
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
USB2COM_DecrementIoCount(DeviceObject);
return ntStatus;
}
// Reset this flag so new IOCTL and IO Irp processing will be re-enabled
deviceExtension->RemoveDeviceRequested = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break; // end, case IRP_MN_CANCEL_REMOVE_DEVICE
case IRP_MN_SURPRISE_REMOVAL:
USB2COM_KdPrint( DBGLVL_MEDIUM,("USB2COM_ProcessPnPIrp() IRP_MN_SURPRISE_REMOVAL\n"));
// For a surprise-style device removal ( i.e. sudden cord yank ),
// the physical device has already been removed so the PnP Manager sends
// the remove IRP without a prior query-remove. A device can be in any state
// when it receives a remove IRP as a result of a surprise-style removal.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -