📄 whusb20pnp.c
字号:
//////////////////////////////////////////////////////////////////////////////
//文件名称:Whceb01Pnp.cpp
//文件功能:即插即用例程
//文件作者:张伟标
//工作部门:研究一室
//创建时间:2003年8月25日
//修改记录:
//版权所有:维豪信息技术有限公司
//
//Copyright 2003 WellHope Information Technology Corporation, Ltd.
//All rights reserved.
/////////////////////////////////////////////////////////////////////////////
// Whceb01AddDevice Add device routine
// Whceb01Pnp PNP IRP dispatcher
// PnpStartDeviceHandler Handle PnP start device
//* PnpQueryCapabilitiesHandler Print pdo device capabilities
//* PnpQueryRemoveDeviceHandler Handle PnP query remove device
//* PnpSurpriseRemovalHandler Handle PnP surprise removal
//* PnpRemoveDeviceHandler Handle PnP remove device
//* PnpStopDeviceHandler Handle PnP stop device
//* PnpStopDevice Handle PnP device stopping
//* PnpDefaultHandler Default PnP handler to pass to next stack device
//* ForwardIrpAndWait Forward IRP and wait for it to complete
//* LockDevice Lock out PnP remove request
//* UnlockDevice Unlock device allow PnP remove request
// Whceb01Power Power IRP handler
//* ForwardedIrpCompletionRoutine Completion routine for ForwardIrpAndWait
/////////////////////////////////////////////////////////////////////////////
#define INITGUID // initialize Whceb01_GUID in this module
#include "Whusb20.h"
#pragma code_seg("PAGE") // start PAGE section
/////////////////////////////////////////////////////////////////////////////
NTSTATUS PnpStartDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS PnpQueryCapabilitiesHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS PnpQueryRemoveDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS PnpSurpriseRemovalHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS PnpRemoveDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS PnpStopDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp);
void PnpStopDevice( IN PWHCEB01_DEVICE_EXTENSION dx);
NTSTATUS PnpDefaultHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp);
NTSTATUS ForwardedIrpCompletionRoutine( IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PKEVENT ev);
/////////////////////////////////////////////////////////////////////////////
// Whceb01AddDevice:
//
// Description:
// Cope with a new PnP device being added here.
// Usually just attach to the top of the driver stack.
// Do not talk to device here!
//
// Arguments:
// Pointer to the Driver object
// Pointer to Physical Device Object
//
// Return Value:
// This function returns STATUS_XXX
NTSTATUS Whceb01AddDevice( IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT pdo)
{
NTSTATUS status;
PDEVICE_OBJECT fdo;
PWHCEB01_DEVICE_EXTENSION dx;
PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
ULONG i = 0;
#ifdef DEBUG_INTERFACE
TRACE0 ("进入Whceb01AddDevice()");
#endif//DEBUG_INTERFACE
// Create our Functional Device Object in fdo
status = IoCreateDevice( DriverObject, sizeof(WHCEB01_DEVICE_EXTENSION), NULL, // No Name
FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);
if( !NT_SUCCESS(status))
return status;
// Remember fdo in our device extension
dx = (PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
dx->fdo = fdo;
dx->pdo = pdo;
dx->UsageCount = 0;
KeInitializeEvent( &dx->StoppingEvent, NotificationEvent, FALSE);
KeInitializeEvent( &dx->WaitEvent , NotificationEvent , FALSE );
KeInitializeMutex( &dx->ChannelMutex , 1 );//信号量
KeInitializeMutex( &dx->FrameMutex , 1 );
dx->OpenHandleCount = 0;
dx->Whceb01NumOfPipes = 0;
dx->GotResources = FALSE;
dx->Paused = FALSE;
dx->IODisabled = TRUE;
dx->Stopping = FALSE;
dx->hWhceb01ConfigurationHandle = NULL;
for( i = 0 ; i < MAX_CHANNEL ; i ++ )
{
dx->hWhceb01InterruptInHandle[i] = NULL;
dx->hWhceb01InterruptOutHandle[i] = NULL;
dx->ChannelisUsed[i] = FALSE;
}
dx->PduHead.Reserved = 0;
dx->UsbTimeout = 10;
// Register and enable our device interface
status = IoRegisterDeviceInterface( pdo, &WHCEB01_GUID, NULL, &dx->ifSymLinkName);
if( !NT_SUCCESS(status))
{
IoDeleteDevice(fdo);
return status;
}
#ifdef DEBUG_INTERFACE
TRACE1("Symbolic Link Name is %T",&dx->ifSymLinkName);
#endif//DEBUG_INTERFACE
// Attach to the driver stack below us
dx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo,pdo);
// Set fdo flags appropriately
fdo->Flags |= DO_BUFFERED_IO|DO_POWER_PAGABLE;
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////////////////////////////
// Whceb01Pnp:
//
// Description:
// Handle IRP_MJ_PNP requests
//
// Arguments:
// Pointer to our FDO
// Pointer to the IRP
// Various minor codes
// IrpStack->Parameters.QueryDeviceRelations
// IrpStack->Parameters.QueryInterface
// IrpStack->Parameters.DeviceCapabilities
// IrpStack->Parameters.FilterResourceRequirements
// IrpStack->Parameters.ReadWriteConfig
// IrpStack->Parameters.SetLock
// IrpStack->Parameters.QueryId
// IrpStack->Parameters.QueryDeviceText
// IrpStack->Parameters.UsageNotification
//
// Return Value:
// This function returns STATUS_XXX
NTSTATUS Whceb01Pnp( IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
{
PWHCEB01_DEVICE_EXTENSION dx=(PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
PIO_STACK_LOCATION IrpStack;
ULONG MinorFunction;
NTSTATUS status;
TRACE0( "Pnp" );
if (!LockDevice(dx))
return CompleteIrp(Irp, STATUS_DELETE_PENDING, 0);
// Get minor function
IrpStack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = IrpStack->MinorFunction;
status = STATUS_SUCCESS;
switch( MinorFunction)
{
case IRP_MN_START_DEVICE:
status = PnpStartDeviceHandler(fdo,Irp);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
status = PnpQueryRemoveDeviceHandler(fdo,Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
status = PnpSurpriseRemovalHandler(fdo,Irp);
break;
case IRP_MN_REMOVE_DEVICE:
status = PnpRemoveDeviceHandler(fdo,Irp);
return status;
case IRP_MN_QUERY_STOP_DEVICE:
dx->Paused = TRUE;
dx->IODisabled = TRUE;
status = PnpDefaultHandler(fdo,Irp);
break;
case IRP_MN_STOP_DEVICE:
status = PnpStopDeviceHandler(fdo,Irp);
break;
case IRP_MN_CANCEL_REMOVE_DEVICE: // fall thru
case IRP_MN_CANCEL_STOP_DEVICE:
dx->Paused = FALSE;
dx->IODisabled = FALSE;
// fall thru
default:
status = PnpDefaultHandler(fdo,Irp);
}
UnlockDevice(dx);
//#if DBG
// if( status!=STATUS_SUCCESS)
// DebugPrint("PnP completed %x",status);
//#endif
return status;
}
/////////////////////////////////////////////////////////////////////////////
// PnpStartDeviceHandler: Handle PnP start device
NTSTATUS PnpStartDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
NTSTATUS status;
PWHCEB01_DEVICE_EXTENSION dx=(PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
PIO_STACK_LOCATION IrpStack ;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
#ifdef DEBUG_INTERFACE
TRACE0("-------进入PnpStartDeviceHandler!----------");
#endif//DEBUG_INTERFACE
status = ForwardIrpAndWait( fdo, Irp);
if( !NT_SUCCESS(status))
return CompleteIrp( Irp, status, Irp->IoStatus.Information);
status = StartDevice( dx, IrpStack->Parameters.StartDevice.AllocatedResourcesTranslated);
if( NT_SUCCESS(status))
{
dx->Paused = FALSE;
dx->IODisabled = FALSE;
IoSetDeviceInterfaceState( &dx->ifSymLinkName, TRUE);
}
#ifdef DEBUG_INTERFACE
TRACE0("-----------Exit PnpStartDeviceHandler.---------------");
#endif//DEBUG_INTERFACE
return CompleteIrp( Irp, status, 0);
}
/////////////////////////////////////////////////////////////////////////////
// PnpQueryRemoveDeviceHandler: Handle PnP query remove device
NTSTATUS PnpQueryRemoveDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
PWHCEB01_DEVICE_EXTENSION dx=(PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
TRACE0("Enter PnpQueryRemoveDeviceHandler");
if( dx->OpenHandleCount>0)
{
TRACE1("PnpQueryRemoveDeviceHandler: %d handles still open",dx->OpenHandleCount);
return CompleteIrp( Irp, STATUS_UNSUCCESSFUL, 0);
}
dx->Paused = TRUE;
dx->IODisabled = TRUE;
return PnpDefaultHandler(fdo,Irp);
}
/////////////////////////////////////////////////////////////////////////////
// PnpSurpriseRemovalHandler: Handle PnP surprise removal
NTSTATUS PnpSurpriseRemovalHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
PWHCEB01_DEVICE_EXTENSION dx=(PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
TRACE0("Enter PnpSurpriseRemovalHandler");
// Wait for I/O to complete and stop device
PnpStopDevice(dx);
// Pass down stack and carry on immediately
return PnpDefaultHandler(fdo, Irp);
}
/////////////////////////////////////////////////////////////////////////////
// PnpRemoveDeviceHandler: Handle PnP remove device
NTSTATUS PnpRemoveDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
NTSTATUS status;
PWHCEB01_DEVICE_EXTENSION dx=(PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
TRACE0("Enter PnpRemoveDeviceHandler");
// Wait for I/O to complete and stop device
PnpStopDevice(dx);
// Pass down stack and carry on immediately
status = PnpDefaultHandler(fdo, Irp);
// disable device interface
IoSetDeviceInterfaceState( &dx->ifSymLinkName, FALSE);
RtlFreeUnicodeString(&dx->ifSymLinkName);
// unattach from stack
if (dx->NextStackDevice)
IoDetachDevice(dx->NextStackDevice);
// delete our fdo
IoDeleteDevice(fdo);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// PnpStopDeviceHandler: Handle PnP stop device
NTSTATUS PnpStopDeviceHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
PWHCEB01_DEVICE_EXTENSION dx=(PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
TRACE0("Enter PnpStopDeviceHandler");
// Wait for I/O to complete and stop device
PnpStopDevice(dx);
return PnpDefaultHandler( fdo, Irp);
}
/////////////////////////////////////////////////////////////////////////////
// PnpStopDevice: Handle PnP device stopping
void PnpStopDevice( IN PWHCEB01_DEVICE_EXTENSION dx)
{
TRACE0 ("Enter PnpStopDevice");
// Stop I/O ASAP
dx->IODisabled = TRUE;
// Do nothing if we're already stopped
if( !dx->GotResources)
return;
// Wait for any pending I/O operations to complete
dx->Stopping = TRUE;
KeResetEvent(&dx->StoppingEvent);
// UnlockDevice(dx);
UnlockDevice(dx);
TRACE1( "before WaitFor 0x%x" , dx->UsageCount );
KeWaitForSingleObject( &dx->StoppingEvent, Executive, KernelMode, FALSE, NULL);
TRACE0( "after WaitFor" );
//DebugPrint("PnpStopDevice: All pending I/O completed");
dx->Stopping = FALSE;
// Stop our device before passing down
StopDevice(dx);
// Bump usage count back up again
LockDevice(dx);
LockDevice(dx);
}
/////////////////////////////////////////////////////////////////////////////
// Support routines
/////////////////////////////////////////////////////////////////////////////
// PnpDefaultHandler: Default PnP handler to pass to next stack device
NTSTATUS PnpDefaultHandler( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
// DebugPrintMsg("PnpDefaultHandler");
PWHCEB01_DEVICE_EXTENSION dx=(PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver( dx->NextStackDevice, Irp);
}
/////////////////////////////////////////////////////////////////////////////
// ForwardIrpAndWait: Forward IRP and wait for it to complete
NTSTATUS ForwardIrpAndWait( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
NTSTATUS status;
PWHCEB01_DEVICE_EXTENSION dx=(PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
KEVENT event;
KeInitializeEvent( &event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)ForwardedIrpCompletionRoutine,
(PVOID)&event, TRUE, TRUE, TRUE);
status = IoCallDriver( dx->NextStackDevice, Irp);
if( status==STATUS_PENDING)
{
DebugPrintMsg("ForwardIrpAndWait: waiting for completion");
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL);
status = Irp->IoStatus.Status;
}
#ifdef DEBUG_INTERFACE
if( status!=STATUS_SUCCESS)
TRACE1("ForwardIrpAndWait: completed %x",status);
#endif
return status;
}
/////////////////////////////////////////////////////////////////////////////
// LockDevice: Lock out PnP remove request
BOOL LockDevice( IN PWHCEB01_DEVICE_EXTENSION dx)
{
// TRACE0("Enter LockDevice");
InterlockedIncrement(&dx->UsageCount);
if( dx->Stopping)
{
if( InterlockedDecrement(&dx->UsageCount)==0)
KeSetEvent( &dx->StoppingEvent, 0, FALSE);
return FALSE;
}
// TRACE0("Exit LockDevice");
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// UnlockDevice: Unlock device allow PnP remove request
void UnlockDevice( IN PWHCEB01_DEVICE_EXTENSION dx)
{
LONG UsageCount ;
// TRACE0("Enter UnlockDevice");
UsageCount = InterlockedDecrement(&dx->UsageCount);
if( UsageCount==0)
{
KeSetEvent( &dx->StoppingEvent, 0, FALSE);
}
// TRACE0("Exit UnlockDevice");
}
/////////////////////////////////////////////////////////////////////////////
// Whceb01Power:
//
// Description:
// Handle IRP_MJ_POWER requests
//
// Arguments:
// Pointer to the FDO
// Pointer to the IRP
// IRP_MN_WAIT_WAKE: IrpStack->Parameters.WaitWake.Xxx
// IRP_MN_POWER_SEQUENCE: IrpStack->Parameters.PowerSequence.Xxx
// IRP_MN_SET_POWER:
// IRP_MN_QUERY_POWER: IrpStack->Parameters.Power.Xxx
//
// Return Value:
// This function returns STATUS_XXX
NTSTATUS Whceb01Power( IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
{
// DebugPrint("Power %I",Irp);
PWHCEB01_DEVICE_EXTENSION dx = (PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
// Just pass to lower driver
PoStartNextPowerIrp( Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver( dx->NextStackDevice, Irp);
}
/////////////////////////////////////////////////////////////////////////////
#pragma code_seg() // end PAGE section
/////////////////////////////////////////////////////////////////////////////
// ForwardedIrpCompletionRoutine: Completion routine for ForwardIrpAndWait
// Can be called at DISPATCH_LEVEL IRQL
NTSTATUS ForwardedIrpCompletionRoutine( IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PKEVENT ev)
{
KeSetEvent( ev, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -