⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drvpower.c

📁 ddk编写的usb驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "zjHMCFUsb.h"
/************************************************************************************************
* Function Type	:	Global
* Parameter		:	fdo				-	Pointer to the device object for the class device. ( Physical Device Object )
*					MinorFunction		-	Specifies the minor function code in the power IRP. 
*					PowerState		-	Specifies the device power state passed to PoRequestPowerIrp.
*					Context			-	Driver defined context, in this case our FDO ( functional device object )
*					IoStatus			-	Points to the IoStatus block in the completed IRP. 
* Return Value	:	The function value is the final status from the operation.
* Description		:	当驱动完成一个自己创建的IRP时就调用这个例程。
*					这个例程在调用hwSelfSuspendOrActivate()时产生
*					电源在第一个管道打开时打开,最后一个管道关闭时关闭。
*					在电源开启的情况下,我们将设置设备扩展中的一个事件
*					为有信号来表示电源IRP处理完成,因此电源请求可以作为
*					同步调用
*					我们必须知道设备电源是开启的在第一个管道打开的时候
*					比如,在电源关闭的时候我们不会设置一个事件,因为
*					不会有任何调用者会在电源关闭的时候等待irp的完成
*************************************************************************************************/
NTSTATUS hwPoSelfRequestCompletion
(
	IN PDEVICE_OBJECT		fdo, 
	IN UCHAR				MinorFunction,
	IN POWER_STATE			PowerState,
	IN PVOID					Context,
	IN PIO_STATUS_BLOCK		IoStatus
)
{
	PDEVICE_OBJECT			deviceObject = Context;
	PDEVICE_EXTENSION		dx = deviceObject->DeviceExtension;
	NTSTATUS				ntStatus = IoStatus->Status;
	
	// 确保当前不是正在处理系统产生的电源IRP
	hwASSERT( NULL == dx->PowerIrp );
	
	// 我们仅仅在电源打开的情况下才触发事件dx->SelfRequestedPowerIrpEvent
	// 在电源关闭的情况下不会有调用者在等待这个处理完成
	if ( (ULONG) PowerState.DeviceState < dx->PowerDownLevel )
	{
		
		// Trigger Self-requested power irp completed event;
		//  The caller is waiting for completion
		KeSetEvent(&dx->SelfRequestedPowerIrpEvent, 1, FALSE);
	}
	
	hwDecrementIoCount(deviceObject);
	hwDbgPrint("hwPoSelfRequestCompletion() ntStatus = 0x%x\n", ntStatus );
	
    return ntStatus;
}

/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	Pointer to the device object
*					PowerState		-	power state requested, e.g PowerDeviceD0.
* Return Value	:	The function value is the final status from the operation.
* Description		:	This routine is called by hwSelfSuspendOrActivate() to
*					actually make the system request for a power down/up to PowerState.
*					It first checks to see if we are already in Powerstate and immediately
*					returns  SUCCESS with no further processing if so
*					通过系统请求改变电源状态
*************************************************************************************************/
NTSTATUS hwSelfRequestPowerIrp
(
	IN PDEVICE_OBJECT	fdo,
	IN POWER_STATE		PowerState
)
{
	NTSTATUS			ntStatus = STATUS_SUCCESS;
	PDEVICE_EXTENSION	dx;
	dx =  fdo->DeviceExtension;
	
	// This should have been reset in completion routine
	hwASSERT( !dx->SelfPowerIrp );
	
	if (  dx->CurrentDevicePowerState ==  PowerState.DeviceState )
		return STATUS_SUCCESS;		// nothing to do
	
	hwDbgPrint(" -->>>>>> hwSelfRequestPowerIrp() will request power irp to state %s\n",
	        hwStringForDevState( PowerState.DeviceState ));
	
	hwIncrementIoCount(fdo);
	
	// flag we're handling a self-generated power irp
	dx->SelfPowerIrp = TRUE;

	// allocates a power IRP and sends it to the top driver in the device stack for the specified device
	ntStatus = PoRequestPowerIrp(dx->pdo,	// Points to the target device object for the IRP
								IRP_MN_SET_POWER,
								PowerState,				// Specifies a power state to pass in the IRP
								hwPoSelfRequestCompletion,
								fdo,			// Context
								NULL);

	if  ( ntStatus == STATUS_PENDING )
	{
		// 这正是我们想要的返回值
		// 只有在电源开启的情况下才需要等待处理完成的事件
		if ( (ULONG) PowerState.DeviceState < dx->PowerDownLevel )
		{	
			NTSTATUS waitStatus;			
			waitStatus = KeWaitForSingleObject(
				&dx->SelfRequestedPowerIrpEvent,
				Suspended,
				KernelMode,
				FALSE,
				NULL);
		}
		ntStatus = STATUS_SUCCESS;
		dx->SelfPowerIrp = FALSE;
		hwDbgPrint("Request change power state success , PowerState %s\n",
			 hwStringForDevState(PowerState.DeviceState));		
	}
	else
	{
		// The return status was not STATUS_PENDING; any other codes must be considered in error here;
		//  i.e., it is not possible to get a STATUS_SUCCESS  or any other non-error return from this call;
		hwDbgPrint("Request change power state FAILED , state %s , status = 0x%x\n",
			hwStringForDevState( PowerState.DeviceState ),ntStatus);
	}
	return ntStatus;
}

/************************************************************************************************
* Function Type	:	Global
* Parameter		:	fdo		-	Pointer to the device object
*					fSuspend			-	TRUE to Suspend, FALSE to acivate.
* Return Value	:	SUCCESS		-	If the operation is not attemtped
										If the operation is attemtped, the value is the final status from the operation.
* Description		:	Called on zjHMCFUsb_AddDevice() to power down until needed (i.e., till a pipe is actually opened).
*					Called on zjHMCFUsb_Create() to power up device to D0 before opening 1st pipe.
*					Called on zjHMCFUsb_Close() to power down device if this is the last pipe.
*					挂起或激活设备,实际上是改变电源状态
*************************************************************************************************/
NTSTATUS hwSelfSuspendOrActivate
(
	IN PDEVICE_OBJECT	fdo,
	IN BOOLEAN			fSuspend
)
{
	NTSTATUS			ntStatus = STATUS_SUCCESS;	
	POWER_STATE		PowerState;
	PDEVICE_EXTENSION 	dx;	
	dx = fdo->DeviceExtension;
	hwDbgPrint(" -->>>>>> hwSelfSuspendOrActivate(fdo=0x%x,fSuspend = %s\n",fdo, fSuspend?"TRUE":"FALSE");
	
	if ( !hwCanAcceptIoRequests( fdo ) )
	{
		ntStatus = STATUS_DELETE_PENDING;		
		hwDbgPrint("ABORTING hwSelfSuspendOrActivate()\n");
		return ntStatus;
	}
	
	// 如果系统产生的任何设备PNP IRPs正在处理,我们不做任何事情,直接返回
	if ( NULL != dx->PowerIrp )
	{
       	 hwDbgPrint("refusing on pending dx->PowerIrp 0x%I\n", dx->PowerIrp);
       	 goto done;
	}
	
	// 如果自己产生的任何设备PNP IRPs正在处理,我们不做任何事情,直接返回
	if ( dx->SelfPowerIrp )
	{
		hwDbgPrint("refusing on pending dx->SelfPowerIrp\n");
		goto done;
	}
	
	// 如果任何管道被打开了,我们的设备不能自动挂起
	if ( fSuspend && ( 0 != dx->OpenPipeCount ) )
	{
       	 hwDbgPrint("refusing to self-suspend on OpenPipeCount %d\n", dx->OpenPipeCount);
       	 goto done;
        }
	
	// 如果没有管道被打开,我们的设备不能自动激活
	if ( !fSuspend && ( 0 == dx->OpenPipeCount ) )
	{
		hwDbgPrint(" refusing to self-activate, no pipes open\n");
		goto done;
	}
	
	// dont do anything if registry CurrentControlSet\Services\zjHMCFUsb\Parameters\PowerDownLevel
	//  has been set to  zero, PowerDeviceD0 ( 1 ), or a bogus high value
	if ( ( dx->PowerDownLevel == PowerDeviceD0 ) ||
		( dx->PowerDownLevel == PowerDeviceUnspecified)  ||
		( dx->PowerDownLevel >= PowerDeviceMaximum ) )
	{
		hwDbgPrint("refusing on dx->PowerDownLevel == %d\n", dx->PowerDownLevel);
		goto done;
	}	
	if ( fSuspend )
		PowerState.DeviceState = dx->PowerDownLevel;
	else
		PowerState.DeviceState = PowerDeviceD0;  // power up all the way; we're probably just about to do some IO
	
	ntStatus = hwSelfRequestPowerIrp( fdo, PowerState );
	hwDbgPrint("hwSelfSuspendOrActivate() status 0x%x on setting dev state %s\n",
		ntStatus, hwStringForDevState(PowerState.DeviceState ));	
done:
	hwDbgPrint ( "hwSelfSuspendOrActivate() -->>>>>>\n");
	return ntStatus;	
}

/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo				-	Pointer to the device object for the class device.
*										Note that we must get our own device object from the Context
*					Context			-	Driver defined context, in this case our own functional device object ( FDO )
* Return Value	:	The function value is the final status from the operation.
* Description		:	This is the completion routine set in a call to PoRequestPowerIrp()
*					that was made in zjHMCFUsb_PowerIrp() in response to receiving
*					an IRP_MN_SET_POWER of type 'SystemPowerState' when the device was
*					not in a compatible device power state. In this case, a pointer to
*					the IRP_MN_SET_POWER Irp is saved into the FDO device extension
*					(dx->PowerIrp), and then a call must be
*					made to PoRequestPowerIrp() to put the device into a proper power state,
*					and this routine is set as the completion routine.
*					We decrement our pending io count and pass the saved IRP_MN_SET_POWER Irp
*					on to the next driver
*************************************************************************************************/
NTSTATUS zjHMCFUsb_PoRequestCompletion
(
	IN PDEVICE_OBJECT		fdo,
	IN UCHAR				MinorFunction,
	IN POWER_STATE			PowerState,
	IN PVOID					Context,
	IN PIO_STATUS_BLOCK		IoStatus
)
{
	PIRP irp;
	PDEVICE_EXTENSION dx;
	PDEVICE_OBJECT deviceObject = Context;
	NTSTATUS ntStatus;

	hwDbgPrint(" -->>>>>> zjHMCFUsb_PoRequestCompletion()\n");
	PrintCurIrql();
	
	dx = deviceObject->DeviceExtension;
	
	// Get the Irp we saved for later processing in zjHMCFUsb_PowerIrp()
	// when we decided to request the Power Irp that this routine
	// is the completion routine for.
	irp = dx->PowerIrp;
	
	// We will return the status set by the PDO for the power request we're completing
	ntStatus = IoStatus->Status;	
	
	// we should not be in the midst of handling a self-generated power irp
	hwASSERT( !dx->SelfPowerIrp );
	
	// we must pass down to the next driver in the stack
	IoCopyCurrentIrpStackLocationToNext(irp);

	//------------------------------------------------------------------
	// Calling PoStartNextPowerIrp() indicates that the driver is finished
	// with the previous power IRP, if any, and is ready to handle the next power IRP.
	// It must be called for every power IRP.Although power IRPs are completed only once,
	// typically by the lowest-level driver for a device, PoStartNextPowerIrp must be called
	// for every stack location. Drivers must call PoStartNextPowerIrp while the current IRP
	// stack location points to the current driver. Therefore, this routine must be called
	// before IoCompleteRequest, IoSkipCurrentStackLocation, and PoCallDriver.
	//------------------------------------------------------------------
	
	PoStartNextPowerIrp(irp);
	//------------------------------------------------------------------
	// PoCallDriver is used to pass any power IRPs to the PDO instead of IoCallDriver.
	// When passing a power IRP down to a lower-level driver, the caller should use
	// IoSkipCurrentIrpStackLocation or IoCopyCurrentIrpStackLocationToNext to copy the IRP to
	// the next stack location, then call PoCallDriver. Use IoCopyCurrentIrpStackLocationToNext
	// if processing the IRP requires setting a completion routine, or IoSkipCurrentStackLocation
	// if no completion routine is needed.
	//------------------------------------------------------------------
	
	PoCallDriver(dx->LowerDeviceObject,irp);

	hwDecrementIoCount(deviceObject);

	hwDbgPrint("zjHMCFUsb_PoRequestCompletion() Exit IRP_MN_SET_POWER\n");

	dx->PowerIrp = NULL;

	return ntStatus;
}

/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
*					Irp				-	Irp completed.
*					Context			-	Driver defined context.
* Return Value	:	The function value is the final status from the operation.
* Description		:	This routine is called when An IRP_MN_SET_POWER of type 'DevicePowerState'
*					has been received by zjHMCFUsb_PowerIrp(), and that routine has  determined
*					1) the request is for full powerup ( to PowerDeviceD0 ), and
*					2) We are not already in that state
*					A call is then made to PoRequestPowerIrp() with this routine set as the completion routine.
*************************************************************************************************/
NTSTATUS zjHMCFUsb_PowerIrp_Complete(IN PDEVICE_OBJECT NullDeviceObject,IN PIRP Irp,IN PVOID Context)
{
	NTSTATUS ntStatus = STATUS_SUCCESS;
	PDEVICE_OBJECT deviceObject;
	PIO_STACK_LOCATION irpStack;
	PDEVICE_EXTENSION dx;
	
	hwDbgPrint(" -->>>>>> zjHMCFUsb_PowerIrp_Complete\n");
	PrintCurIrql();
	deviceObject = (PDEVICE_OBJECT) Context;
	dx = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;

	//  If the lower driver returned PENDING, mark our stack location as pending also.
	if (Irp->PendingReturned)
	{
		IoMarkIrpPending(Irp);
	}

	irpStack = IoGetCurrentIrpStackLocation (Irp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -