📄 ul_wdpwr.c
字号:
// 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(deviceExtension->DeviceToSendIrpsTo, irp); RequestDecrement(deviceExtension); uLan_DbgPrint("uLan: PoRequestCompletion() Exit IRP_MN_SET_POWER\n"); deviceExtension->PowerIrp = NULL; return ntStatus;}NTSTATUSPowerIrp_Complete( IN PDEVICE_OBJECT NullDeviceObject, IN PIRP Irp, IN PVOID Context )/*++Routine Description: This routine is called when An IRP_MN_SET_POWER of type 'DevicePowerState' has been received by ProcessPowerIrp(), 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.Arguments: DeviceObject - Pointer to the device object for the class device. Irp - Irp completed. Context - Driver defined context.Return Value: The function value is the final status from the operation.--*/{ NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject; PIO_STACK_LOCATION irpStack; PULAN_DEVICE_EXTENSION deviceExtension; uLan_DbgPrint("uLan: enter PowerIrp_Complete\n"); deviceObject = (PDEVICE_OBJECT) Context; deviceExtension = deviceObject->DeviceExtension; // If the lower driver returned PENDING, mark our stack location as pending also. if (Irp->PendingReturned) { IoMarkIrpPending(Irp); } irpStack = IoGetCurrentIrpStackLocation (Irp); // We can assert that we're a device powerup-to D0 request, // because that was the only type of request we set a completion routine // for in the first place ASSERT(irpStack->MajorFunction == IRP_MJ_POWER); ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER); ASSERT(irpStack->Parameters.Power.Type==DevicePowerState); ASSERT(irpStack->Parameters.Power.State.DeviceState==PowerDeviceD0); // Now that we know we've let the lower drivers do what was needed to power up, // we can set our device extension flags accordingly deviceExtension->CurrentDevicePowerState = PowerDeviceD0; Irp->IoStatus.Status = ntStatus; RequestDecrement(deviceExtension); uLan_DbgPrint("uLan: exit PowerIrp_Complete Exit IRP_MN_SET_POWER D0 complete\n"); return ntStatus;}NTSTATUSSelfSuspendOrActivate( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN fSuspend )/*++Routine Description: Called on PnPAddDevice() to power down until needed (i.e., till a pipe is actually opened). Called on Create() to power up device to D0 before opening 1st pipe. Called on Close() to power down device if this is the last pipe.Arguments: DeviceObject - Pointer to the device object fSuspend; TRUE to Suspend, FALSE to acivate.Return Value: If the operation is not attemtped, SUCCESS is returned. If the operation is attemtped, the value is the final status from the operation.--*/{ NTSTATUS ntStatus = STATUS_SUCCESS; POWER_STATE PowerState; PULAN_DEVICE_EXTENSION deviceExtension; deviceExtension = DeviceObject->DeviceExtension; uLan_DbgPrint("uLan: Enter SelfSuspendOrActivate(),fSuspend = %d\n", fSuspend); // Can't accept request if: // 1) device is removed, // 2) has never been started, // 3) is stopped, // 4) has a remove request pending, // 5) has a stop device pending/* if ( !BulkUsb_CanAcceptIoRequests( DeviceObject ) ) { ntStatus = STATUS_DELETE_PENDING; BULKUSB_KdPrint( DBGLVL_MEDIUM,("ABORTING BulkUsb_SelfSuspendOrActivate()\n")); return ntStatus; }*/ // don't do anything if any System-generated Device Pnp irps are pending if ( NULL != deviceExtension->PowerIrp ) { uLan_DbgPrint("uLan: Exit SelfSuspendOrActivate(),refusing on pending deviceExtension->PowerIrp 0x%x\n", deviceExtension->PowerIrp); return ntStatus; } // don't do anything if any self-generated Device Pnp irps are pending if ( deviceExtension->SelfPowerIrp ) { uLan_DbgPrint("uLan: Exit SelfSuspendOrActivate(),refusing on pending deviceExtension->SelfPowerIrp\n" ); return ntStatus; } // has been set to zero, PowerDeviceD0 ( 1 ), or a bogus high value if ( ( deviceExtension->PowerDownLevel == PowerDeviceD0 ) || ( deviceExtension->PowerDownLevel == PowerDeviceUnspecified) || ( deviceExtension->PowerDownLevel >= PowerDeviceMaximum ) ) { uLan_DbgPrint("uLan: Exit SelfSuspendOrActivate(), refusing on deviceExtension->PowerDownLevel == %d\n", deviceExtension->PowerDownLevel); return ntStatus; } if ( fSuspend ) PowerState.DeviceState = deviceExtension->PowerDownLevel; else PowerState.DeviceState = PowerDeviceD0; // power up all the way; we're probably just about to do some IO ntStatus = SelfRequestPowerIrp( DeviceObject, PowerState ); uLan_DbgPrint("uLan: SelfSuspendOrActivate() status 0x%x on setting dev state %s\n", ntStatus, DevicePowerStateString[PowerState.DeviceState]); return ntStatus;}NTSTATUSSelfRequestPowerIrp( IN PDEVICE_OBJECT DeviceObject, IN POWER_STATE PowerState )/*++Routine Description: This routine is called by SelfSuspendOrActivate() to actually make the system request for a powerdown/up to PowerState. It first checks to see if we are already in Powerstate and immediately returns SUCCESS with no further processing if soArguments: DeviceObject - Pointer to the device object PowerState. power state requested, e.g PowerDeviceD0.Return Value: The function value is the final status from the operation.--*/{ NTSTATUS ntStatus = STATUS_SUCCESS; PULAN_DEVICE_EXTENSION deviceExtension; PIRP pIrp = NULL; deviceExtension = DeviceObject->DeviceExtension; // This should have been reset in completion routine ASSERT( !deviceExtension->SelfPowerIrp ); if ( deviceExtension->CurrentDevicePowerState == PowerState.DeviceState ) return STATUS_SUCCESS; // nothing to do uLan_DbgPrint("uLan: Enter SelfRequestPowerIrp() will request power irp to state %s\n", DevicePowerStateString[PowerState.DeviceState]); RequestIncrement(deviceExtension); // flag we're handling a self-generated power irp deviceExtension->SelfPowerIrp = TRUE; // actually request the Irp ntStatus = PoRequestPowerIrp(deviceExtension->DeviceObject, IRP_MN_SET_POWER, PowerState, PoSelfRequestCompletion, DeviceObject, NULL); if ( ntStatus == STATUS_PENDING ) { // status pending is the return code we wanted // We only need to wait for completion if we're powering up if ( (ULONG) PowerState.DeviceState < deviceExtension->PowerDownLevel ) { NTSTATUS waitStatus; waitStatus = KeWaitForSingleObject( &deviceExtension->SelfRequestedPowerIrpEvent, Suspended, KernelMode, FALSE, NULL); } ntStatus = STATUS_SUCCESS; deviceExtension->SelfPowerIrp = FALSE; uLan_DbgPrint("uLan: SelfRequestPowerIrp() SUCCESS\n IRP 0x%x to state %s\n", pIrp, DevicePowerStateString[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; uLan_DbgPrint("uLan: SelfRequestPowerIrp() to state %s FAILED, status = 0x%x\n", DevicePowerStateString[ PowerState.DeviceState ],ntStatus); } return ntStatus;}NTSTATUSPoSelfRequestCompletion( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus )/*++Routine Description: This routine is called when the driver completes a self-originated power IRP that was generated by a call to SelfSuspendOrActivate(). We power down whenever the last pipe is closed and power up when the first pipe is opened. For power-up , we set an event in our FDO extension to signal this IRP done so the power request can be treated as a synchronous call. We need to know the device is powered up before opening the first pipe, for example. For power-down, we do not set the event, as no caller waits for powerdown complete.Arguments: DeviceObject - Pointer to the device object for the class device. ( Physical Device Object ) Context - Driver defined context, in this case our FDO ( functional device object )Return Value: The function value is the final status from the operation.--*/{ PDEVICE_OBJECT deviceObject = Context; PULAN_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; NTSTATUS ntStatus = IoStatus->Status; // we should not be in the midst of handling a system-generated power irp ASSERT( NULL == deviceExtension->PowerIrp ); // We only need to set the event if we're powering up; // No caller waits on power down complete if ( (ULONG) PowerState.DeviceState < deviceExtension->PowerDownLevel ) { // Trigger Self-requested power irp completed event; // The caller is waiting for completion KeSetEvent(&deviceExtension->SelfRequestedPowerIrpEvent, 1, FALSE); } RequestDecrement(deviceExtension); uLan_DbgPrint("uLan: Exit PoSelfRequestCompletion() ntStatus = 0x%x\n", ntStatus ); return ntStatus;}BOOLEANSetDevicePowerState( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_POWER_STATE DeviceState )/*++Routine Description: This routine is called when An IRP_MN_SET_POWER of type 'DevicePowerState' has been received by Usb_ProcessPowerIrp().Arguments: DeviceObject - Pointer to the device object for the class device. DeviceState - Device specific power state to set the device in to.Return Value: For requests to DeviceState D0 ( fully on ), returns TRUE to signal caller that we must set a completion routine and finish there.--*/{ NTSTATUS ntStatus = STATUS_SUCCESS; PULAN_DEVICE_EXTENSION deviceExtension; BOOLEAN fRes = FALSE; deviceExtension = (PULAN_DEVICE_EXTENSION)DeviceObject->DeviceExtension; switch (DeviceState) { case PowerDeviceD3: // // Device will be going OFF, // TODO: add any needed device-dependent code to save state here. // ( We have nothing to do in this sample ) // uLan_DbgPrint("uLan: SetDevicePowerState() PowerDeviceD3 (OFF)\n"); deviceExtension->CurrentDevicePowerState = DeviceState; break; case PowerDeviceD1: case PowerDeviceD2: // // power states D1,D2 translate to USB suspend uLan_DbgPrint("uLan: SetDevicePowerState() %s\n", DevicePowerStateString[DeviceState]); deviceExtension->CurrentDevicePowerState = DeviceState; break; case PowerDeviceD0: uLan_DbgPrint("uLan: SetDevicePowerState() PowerDeviceD0 (ON)\n"); // We'll need to finish the rest in the completion routine; // signal caller we're going to D0 and will need to set a completion routine fRes = TRUE; // Caller will pass on to PDO ( Physical Device object ) break; default: uLan_DbgPrint("uLan: Bogus DeviceState = %x\n", DeviceState); } return fRes;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -