?? buspdo.c
字號:
/*++
Copyright (c) 2004 Chingachguk & Denger2k All Rights Reserved
Module Name:
BusPdo.c
Abstract:
This module handles plug & play calls for the child PDO.
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include <ntddk.h>
#include ".\Include\driver.h"
#include "vusb.h"
#include "stdio.h"
#include <wdmguid.h>
#define VENDORNAME L"Aladdin "
#define MODEL L"USB Key"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, Bus_PDO_PnP)
#pragma alloc_text (PAGE, Bus_PDO_QueryDeviceCaps)
#pragma alloc_text (PAGE, Bus_PDO_QueryDeviceId)
#pragma alloc_text (PAGE, Bus_PDO_QueryDeviceText)
#pragma alloc_text (PAGE, Bus_PDO_QueryResources)
#pragma alloc_text (PAGE, Bus_PDO_QueryResourceRequirements)
#pragma alloc_text (PAGE, Bus_PDO_QueryDeviceRelations)
#pragma alloc_text (PAGE, Bus_PDO_QueryBusInformation)
#pragma alloc_text (PAGE, Bus_GetDeviceCapabilities)
#pragma alloc_text (PAGE, Bus_LoadDumpsFromRegistry)
#endif
NTSTATUS
Bus_PDO_PnP (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack,
IN PPDO_DEVICE_DATA DeviceData
)
/*++
Routine Description:
Handle requests from the Plug & Play system for the devices on the BUS
--*/
{
NTSTATUS status;
PAGED_CODE ();
//
// NB: Because we are a bus enumerator, we have no one to whom we could
// defer these irps. Therefore we do not pass them down but merely
// return them.
//
switch (IrpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
//
// Here we do what ever initialization and ``turning on'' that is
// required to allow others to access this device.
// Power up the device.
//
DeviceData->DevicePowerState = PowerDeviceD0;
SET_NEW_PNP_STATE(DeviceData, Started);
status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE:
//
// Here we shut down the device and give up and unmap any resources
// we acquired for the device.
//
SET_NEW_PNP_STATE(DeviceData, Stopped);
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_STOP_DEVICE:
//
// No reason here why we can't stop the device.
// If there were a reason we should speak now, because answering success
// here may result in a stop device irp.
//
SET_NEW_PNP_STATE(DeviceData, StopPending);
status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_STOP_DEVICE:
//
// The stop was canceled. Whatever state we set, or resources we put
// on hold in anticipation of the forthcoming STOP device IRP should be
// put back to normal. Someone, in the long list of concerned parties,
// has failed the stop device query.
//
//
// First check to see whether you have received cancel-stop
// without first receiving a query-stop. This could happen if someone
// above us fails a query-stop and passes down the subsequent
// cancel-stop.
//
if(StopPending == DeviceData->DevicePnPState)
{
//
// We did receive a query-stop, so restore.
//
RESTORE_PREVIOUS_PNP_STATE(DeviceData);
}
status = STATUS_SUCCESS;// We must not fail this IRP.
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
//
// Check to see whether the device can be removed safely.
// If not fail this request. This is the last opportunity
// to do so.
//
if(DeviceData->VUsbInterfaceRefCount){
//
// Somebody is still using our interface.
// We must fail remove.
//
status = STATUS_UNSUCCESSFUL;
break;
}
SET_NEW_PNP_STATE(DeviceData, RemovePending);
status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
//
// Clean up a remove that did not go through.
//
//
// First check to see whether you have received cancel-remove
// without first receiving a query-remove. This could happen if
// someone above us fails a query-remove and passes down the
// subsequent cancel-remove.
//
if(RemovePending == DeviceData->DevicePnPState)
{
//
// We did receive a query-remove, so restore.
//
RESTORE_PREVIOUS_PNP_STATE(DeviceData);
}
status = STATUS_SUCCESS; // We must not fail this IRP.
break;
case IRP_MN_SURPRISE_REMOVAL:
//
// We should stop all access to the device and relinquish all the
// resources. Let's just mark that it happened and we will do
// the cleanup later in IRP_MN_REMOVE_DEVICE.
//
SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
//
// Present is set to true when the pdo is exposed via PlugIn IOCTL.
// It is set to FALSE when a UnPlug IOCTL is received.
// We will delete the PDO only after we have reported to the
// Plug and Play manager that it's missing.
//
if (DeviceData->ReportedMissing) {
PFDO_DEVICE_DATA fdoData;
SET_NEW_PNP_STATE(DeviceData, Deleted);
//
// Remove the PDO from the list and decrement the count of PDO.
// Don't forget to synchronize access to the FDO data.
// If the parent FDO is deleted before child PDOs, the ParentFdo
// pointer will be NULL. This could happen if the child PDO
// is in a SurpriseRemovePending state when the parent FDO
// is removed.
//
if(DeviceData->ParentFdo) {
fdoData = FDO_FROM_PDO(DeviceData);
ExAcquireFastMutex (&fdoData->Mutex);
RemoveEntryList (&DeviceData->Link);
fdoData->NumPDOs--;
ExReleaseFastMutex (&fdoData->Mutex);
}
//
// Free up resources associated with PDO and delete it.
//
status = Bus_DestroyPdo(DeviceObject, DeviceData);
break;
}
if (DeviceData->Present) {
//
// When the device is disabled, the PDO transitions from
// RemovePending to NotStarted. We shouldn't delete
// the PDO because a) the device is still present on the bus,
// b) we haven't reported missing to the PnP manager.
//
SET_NEW_PNP_STATE(DeviceData, NotStarted);
status = STATUS_SUCCESS;
} else {
ASSERT(DeviceData->Present);
status = STATUS_SUCCESS;
}
break;
case IRP_MN_QUERY_CAPABILITIES:
//
// Return the capabilities of a device, such as whether the device
// can be locked or ejected..etc
//
status = Bus_PDO_QueryDeviceCaps(DeviceData, Irp);
break;
case IRP_MN_QUERY_ID:
// Query the IDs of the device
Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
("\tQueryId Type: %s\n",
DbgDeviceIDString(IrpStack->Parameters.QueryId.IdType)));
status = Bus_PDO_QueryDeviceId(DeviceData, Irp);
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
IrpStack->Parameters.QueryDeviceRelations.Type)));
status = Bus_PDO_QueryDeviceRelations(DeviceData, Irp);
break;
case IRP_MN_QUERY_DEVICE_TEXT:
status = Bus_PDO_QueryDeviceText(DeviceData, Irp);
break;
case IRP_MN_QUERY_RESOURCES:
status = Bus_PDO_QueryResources(DeviceData, Irp);
break;
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
status = Bus_PDO_QueryResourceRequirements(DeviceData, Irp);
break;
case IRP_MN_QUERY_BUS_INFORMATION:
status = Bus_PDO_QueryBusInformation(DeviceData, Irp);
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
//
// OPTIONAL for bus drivers.
// This bus drivers any of the bus's descendants
// (child device, child of a child device, etc.) do not
// contain a memory file namely paging file, dump file,
// or hibernation file. So we fail this Irp.
//
status = STATUS_UNSUCCESSFUL;
break;
case IRP_MN_EJECT:
//
// For the device to be ejected, the device must be in the D3
// device power state (off) and must be unlocked
// (if the device supports locking). Any driver that returns success
// for this IRP must wait until the device has been ejected before
// completing the IRP.
//
DeviceData->Present = FALSE;
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_INTERFACE:
//
// This request enables a driver to export a direct-call
// interface to other drivers. A bus driver that exports
// an interface must handle this request for its child
// devices (child PDOs).
//
status = Bus_PDO_QueryInterface(DeviceData, Irp);
break;
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
//
// OPTIONAL for bus drivers.
// The PnP Manager sends this IRP to a device
// stack so filter and function drivers can adjust the
// resources required by the device, if appropriate.
//
//break;
//case IRP_MN_QUERY_PNP_DEVICE_STATE:
//
// OPTIONAL for bus drivers.
// The PnP Manager sends this IRP after the drivers for
// a device return success from the IRP_MN_START_DEVICE
// request. The PnP Manager also sends this IRP when a
// driver for the device calls IoInvalidateDeviceState.
//
// break;
//case IRP_MN_READ_CONFIG:
//case IRP_MN_WRITE_CONFIG:
//
// Bus drivers for buses with configuration space must handle
// this request for their child devices. Our devices don't
// have a config space.
//
// break;
//case IRP_MN_SET_LOCK:
//
// Our device is not a lockable device
// so we don't support this Irp.
//
// break;
default:
//
//Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,("\t Not handled\n"));
// For PnP requests to the PDO that we do not understand we should
// return the IRP WITHOUT setting the status or information fields.
// These fields may have already been set by a filter (eg acpi).
status = Irp->IoStatus.Status;
break;
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
Bus_PDO_QueryDeviceCaps(
IN PPDO_DEVICE_DATA DeviceData,
IN PIRP Irp )
/*++
Routine Description:
When a device is enumerated, but before the function and
filter drivers are loaded for the device, the PnP Manager
sends an IRP_MN_QUERY_CAPABILITIES request to the parent
bus driver for the device. The bus driver must set any
relevant values in the DEVICE_CAPABILITIES structure and
return it to the PnP Manager.
Arguments:
DeviceData - Pointer to the PDO's device extension.
Irp - Pointer to the irp.
Return Value:
NT STATUS
--*/
{
PIO_STACK_LOCATION stack;
PDEVICE_CAPABILITIES deviceCapabilities;
DEVICE_CAPABILITIES parentCapabilities;
NTSTATUS status;
PAGED_CODE ();
stack = IoGetCurrentIrpStackLocation (Irp);
//
// Get the packet.
//
deviceCapabilities=stack->Parameters.DeviceCapabilities.Capabilities;
//
// Set the capabilities.
//
if(deviceCapabilities->Version != 1 ||
deviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
{
return STATUS_UNSUCCESSFUL;
}
//
// Get the device capabilities of the parent
//
status = Bus_GetDeviceCapabilities(
FDO_FROM_PDO(DeviceData)->NextLowerDriver, &parentCapabilities);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -