NTSTATUS UsbDev::SendDeviceSetPower( DEVICE_POWER_STATE devpower, BOOL bWait) { POWER_STATE poState; NTSTATUS ntStatus; poState.DeviceState = devpower; if (bWait) { KEVENT Event; USB_SDSP_CONTEXT context; KeInitializeEvent(&Event, NotificationEvent, FALSE); context.pEvent = &Event; ntStatus = PoRequestPowerIrp(m_pLdo, IRP_MN_SET_POWER, poState, (PREQUEST_POWER_COMPLETE) SendDeviceSetPowerComplete, &context, NULL); if (ntStatus == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); ntStatus = context.ntStatus; } } else ntStatus = PoRequestPowerIrp(m_pLdo, IRP_MN_SET_POWER, poState, NULL, NULL, NULL); DBGU_WARNING("SendDeviceSetPower D%d return %X\n", (devpower-1), ntStatus); return ntStatus; }
void power_set_device_state(libusb_device_t *dev, DEVICE_POWER_STATE device_state, bool_t block) { NTSTATUS status; KEVENT event; POWER_STATE power_state; power_state.DeviceState = device_state; USBMSG("setting device power state to D%d %s\n", power_state.DeviceState - PowerDeviceD0, dev->device_id); if (block) /* wait for IRP to complete */ { KeInitializeEvent(&event, NotificationEvent, FALSE); /* set the device power state and wait for completion */ status = PoRequestPowerIrp(dev->physical_device_object, IRP_MN_SET_POWER, power_state, on_power_set_device_state_complete, &event, NULL); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); } } else { PoRequestPowerIrp(dev->physical_device_object, IRP_MN_SET_POWER, power_state, NULL, NULL, NULL); } }
NTSTATUS NTAPI PcRequestNewPowerState( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_POWER_STATE RequestedNewState) { KEVENT Event; NTSTATUS Status; POWER_STATE PowerState; PPCLASS_DEVICE_EXTENSION DeviceExt; PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); if (!DeviceObject || !RequestedNewState) return STATUS_INVALID_PARAMETER; DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; KeInitializeEvent(&Event, SynchronizationEvent, FALSE); PowerState.DeviceState = RequestedNewState; PowerState.SystemState = PowerSystemUnspecified; Status = PoRequestPowerIrp(DeviceExt->PhysicalDeviceObject, IRP_MN_SET_POWER, PowerState, PwrCompletionCallback, (PVOID)&Event, NULL); if (NT_SUCCESS(Status)) { KeWaitForSingleObject((PVOID)&Event, Executive, KernelMode, FALSE, NULL); } return Status; }
static NTSTATUS vboxUsbPwrIoRequestDev(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp) { PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp); POWER_STATE PwrState; PwrState.SystemState = pSl->Parameters.Power.State.SystemState; PwrState.DeviceState = pDevExt->DdiState.DevCaps.DeviceState[PwrState.SystemState]; NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; PVBOXUSB_PWRDEV_CTX pDevCtx = (PVBOXUSB_PWRDEV_CTX)vboxUsbMemAlloc(sizeof (*pDevCtx)); Assert(pDevCtx); if (pDevCtx) { pDevCtx->pDevExt = pDevExt; pDevCtx->pIrp = pIrp; Status = PoRequestPowerIrp(pDevExt->pPDO, pSl->MinorFunction, PwrState, vboxUsbPwrIoDeviceCompletion, pDevCtx, NULL); Assert(NT_SUCCESS(Status)); if (NT_SUCCESS(Status)) { return STATUS_MORE_PROCESSING_REQUIRED; } vboxUsbMemFree(pDevCtx); } PoStartNextPowerIrp(pIrp); pIrp->IoStatus.Status = Status; pIrp->IoStatus.Information = 0; vboxUsbDdiStateRelease(pDevExt); /* the "real" Status is stored in pIrp->IoStatus.Status, * return success here to complete the Io */ return STATUS_SUCCESS; }
NTSTATUS NTAPI IssueWaitWake(IN PDEVICE_EXTENSION DeviceExtension) { POWER_STATE poState; NTSTATUS ntStatus; FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Entered\n")); if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1)) { return STATUS_DEVICE_BUSY; } InterlockedExchange(&DeviceExtension->FlagWWCancel, 0); // lowest state from which this Irp will wake the system poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake; ntStatus = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IRP_MN_WAIT_WAKE, poState, (PREQUEST_POWER_COMPLETE) WaitWakeCallback, DeviceExtension, &DeviceExtension->WaitWakeIrp); if(!NT_SUCCESS(ntStatus)) { InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0); } FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Leaving\n")); return ntStatus; }
NTSTATUS NTAPI USBH_HubSetD0(IN PUSBHUB_FDO_EXTENSION HubExtension) { PUSBHUB_FDO_EXTENSION RootHubDevExt; NTSTATUS Status; KEVENT Event; POWER_STATE PowerState; DPRINT("USBH_HubSetD0: HubExtension - %p\n", HubExtension); RootHubDevExt = USBH_GetRootHubExtension(HubExtension); if (RootHubDevExt->SystemPowerState.SystemState != PowerSystemWorking) { Status = STATUS_INVALID_DEVICE_STATE; return Status; } if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST) { DPRINT("USBH_HubSetD0: HubFlags - %lX\n", HubExtension->HubFlags); KeWaitForSingleObject(&HubExtension->IdleEvent, Suspended, KernelMode, FALSE, NULL); } KeInitializeEvent(&Event, NotificationEvent, FALSE); PowerState.DeviceState = PowerDeviceD0; Status = PoRequestPowerIrp(HubExtension->LowerPDO, IRP_MN_SET_POWER, PowerState, USBH_HubESDRecoverySetD3Completion, &Event, NULL); if (Status == STATUS_PENDING) { Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); } while (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAKEUP_START) { USBH_Wait(10); } return Status; }
VOID NTAPI WaitWakeCallback( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus) { NTSTATUS ntStatus; POWER_STATE powerState; PDEVICE_EXTENSION deviceExtension; FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) Context; InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0); if(!NT_SUCCESS(IoStatus->Status)) { return; } // wake up the device if(deviceExtension->DevPower == PowerDeviceD0) { FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Device already powered up...\n")); return; } FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback::")); FreeBT_IoIncrement(deviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc, deviceExtension, NULL); if(deviceExtension->WaitWakeEnable) { IssueWaitWake(deviceExtension); } FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Leaving\n")); return; }
NTSTATUS IssueWaitWake( IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: This routine will PoRequest a WAIT WAKE irp for the device Arguments: DeviceExtension - pointer to device extension Return Value: NT status value. --*/ { POWER_STATE poState; NTSTATUS ntStatus; MobiUsb_DbgPrint(3, ("file mobipwr: IssueWaitWake - begins\n")); if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1)) { return STATUS_DEVICE_BUSY; } InterlockedExchange(&DeviceExtension->FlagWWCancel, 0); // // lowest state from which this Irp will wake the system // poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake; ntStatus = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IRP_MN_WAIT_WAKE, poState, (PREQUEST_POWER_COMPLETE) WaitWakeCallback, DeviceExtension, &DeviceExtension->WaitWakeIrp); if(!NT_SUCCESS(ntStatus)) { InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0); } MobiUsb_DbgPrint(3, ("file mobipwr: IssueWaitWake - ends\n")); return ntStatus; }
static VOID IdleNotificationCallback(IN PTDeviceExtension DeviceExtension) { NTSTATUS ntStatus; POWER_STATE powerState; KEVENT irpCompletionEvent; PTIrpCompletionContext irpContext; BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback - process\n")); if(DeviceExtension->DeviceState != WORKING) return; if(DeviceExtension->WaitWakeEnable) IssueWaitWake(DeviceExtension); irpContext = (PTIrpCompletionContext)ExAllocatePool(NonPagedPool, sizeof(TIrpCompletionContext)); if(!irpContext) { BulkUsb_DbgPrint(1, ("file bulkdev: Failed to alloc memory for irpContext\n")); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; return; } BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = DeviceExtension->PowerDownLevel; KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE); irpContext->DeviceExtension = DeviceExtension; irpContext->Event = &irpCompletionEvent; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc, irpContext, NULL); if(STATUS_PENDING == ntStatus) { BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback::" "waiting for the power irp to complete\n")); KeWaitForSingleObject(&irpCompletionEvent, Executive, KernelMode, FALSE, NULL); } ExFreePool(irpContext); BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback - ends\n")); }
_Must_inspect_result_ FORCEINLINE NTSTATUS FxIrp::RequestPowerIrp( __in MdDeviceObject DeviceObject, __in UCHAR MinorFunction, __in POWER_STATE PowerState, __in MdRequestPowerComplete CompletionFunction, __in PVOID Context ) { // // Prefast enforces that NULL is passed for IRP parameter (last parameter) // since the IRP might complete before the function returns. // return PoRequestPowerIrp( DeviceObject, MinorFunction, PowerState, CompletionFunction, Context, NULL); }
VOID NTAPI SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp ) { NTSTATUS ntStatus; POWER_STATE powState; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; SYSTEM_POWER_STATE systemState; DEVICE_POWER_STATE devState; PPOWER_COMPLETION_CONTEXT powerContext; irpStack = IoGetCurrentIrpStackLocation(SIrp); systemState = irpStack->Parameters.Power.State.SystemState; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Entered\n")); // Read out the D-IRP out of the S->D mapping array captured in QueryCap's. // we can choose deeper sleep states than our mapping but never choose // lighter ones. devState = deviceExtension->DeviceCapabilities.DeviceState[systemState]; powState.DeviceState = devState; powerContext = (PPOWER_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT)); if (!powerContext) { FreeBT_DbgPrint(1, ("FBTUSB: SendDeviceIrp: Failed to alloc memory for powerContext\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } else { powerContext->DeviceObject = DeviceObject; powerContext->SIrp = SIrp; // in win2k PoRequestPowerIrp can take fdo or pdo. ntStatus = PoRequestPowerIrp( deviceExtension->PhysicalDeviceObject, irpStack->MinorFunction, powState, (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine, powerContext, NULL); } if (!NT_SUCCESS(ntStatus)) { if (powerContext) { ExFreePool(powerContext); } PoStartNextPowerIrp(SIrp); SIrp->IoStatus.Status = ntStatus; SIrp->IoStatus.Information = 0; IoCompleteRequest(SIrp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp::")); FreeBT_IoDecrement(deviceExtension); } FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Leaving\n")); }
NTSTATUS NTAPI USBH_FdoPower(IN PUSBHUB_FDO_EXTENSION HubExtension, IN PIRP Irp, IN UCHAR Minor) { NTSTATUS Status; PIO_STACK_LOCATION IoStack; POWER_STATE PowerState; POWER_STATE DevicePwrState; BOOLEAN IsAllPortsD3; PUSBHUB_PORT_DATA PortData; PDEVICE_OBJECT PdoDevice; PUSBHUB_PORT_PDO_EXTENSION PortExtension; ULONG Port; DPRINT_PWR("USBH_FdoPower: HubExtension - %p, Irp - %p, Minor - %X\n", HubExtension, Irp, Minor); switch (Minor) { case IRP_MN_WAIT_WAKE: DPRINT_PWR("USBH_FdoPower: IRP_MN_WAIT_WAKE\n"); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, USBH_FdoWWIrpIoCompletion, HubExtension, TRUE, TRUE, TRUE); PoStartNextPowerIrp(Irp); IoMarkIrpPending(Irp); PoCallDriver(HubExtension->LowerDevice, Irp); return STATUS_PENDING; case IRP_MN_POWER_SEQUENCE: DPRINT_PWR("USBH_FdoPower: IRP_MN_POWER_SEQUENCE\n"); break; case IRP_MN_SET_POWER: DPRINT_PWR("USBH_FdoPower: IRP_MN_SET_POWER\n"); IoStack = IoGetCurrentIrpStackLocation(Irp); DPRINT_PWR("USBH_FdoPower: IRP_MN_SET_POWER/DevicePowerState\n"); PowerState = IoStack->Parameters.Power.State; if (IoStack->Parameters.Power.Type == DevicePowerState) { DPRINT_PWR("USBH_FdoPower: PowerState - %x\n", PowerState.DeviceState); if (HubExtension->CurrentPowerState.DeviceState == PowerState.DeviceState) { IoCopyCurrentIrpStackLocationToNext(Irp); PoStartNextPowerIrp(Irp); IoMarkIrpPending(Irp); PoCallDriver(HubExtension->LowerDevice, Irp); return STATUS_PENDING; } switch (PowerState.DeviceState) { case PowerDeviceD0: if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_SET_D0_STATE)) { HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_NOT_D0_STATE | USBHUB_FDO_FLAG_DEVICE_STOPPING); HubExtension->HubFlags |= USBHUB_FDO_FLAG_SET_D0_STATE; IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, USBH_PowerIrpCompletion, HubExtension, TRUE, TRUE, TRUE); } else { IoCopyCurrentIrpStackLocationToNext(Irp); PoStartNextPowerIrp(Irp); } IoMarkIrpPending(Irp); PoCallDriver(HubExtension->LowerDevice, Irp); return STATUS_PENDING; case PowerDeviceD1: case PowerDeviceD2: case PowerDeviceD3: if (HubExtension->ResetRequestCount) { IoCancelIrp(HubExtension->ResetPortIrp); KeWaitForSingleObject(&HubExtension->ResetEvent, Executive, KernelMode, FALSE, NULL); } if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED)) { HubExtension->HubFlags |= (USBHUB_FDO_FLAG_NOT_D0_STATE | USBHUB_FDO_FLAG_DEVICE_STOPPING); IoCancelIrp(HubExtension->SCEIrp); KeWaitForSingleObject(&HubExtension->StatusChangeEvent, Executive, KernelMode, FALSE, NULL); } HubExtension->CurrentPowerState.DeviceState = PowerState.DeviceState; if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DO_SUSPENSE && USBH_CheckIdleAbort(HubExtension, TRUE, TRUE) == TRUE) { HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_NOT_D0_STATE | USBHUB_FDO_FLAG_DEVICE_STOPPING); HubExtension->CurrentPowerState.DeviceState = PowerDeviceD0; USBH_SubmitStatusChangeTransfer(HubExtension); PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DO_SUSPENSE; KeReleaseSemaphore(&HubExtension->IdleSemaphore, LOW_REALTIME_PRIORITY, 1, FALSE); return STATUS_UNSUCCESSFUL; } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, USBH_PowerIrpCompletion, HubExtension, TRUE, TRUE, TRUE); PoStartNextPowerIrp(Irp); IoMarkIrpPending(Irp); PoCallDriver(HubExtension->LowerDevice, Irp); if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DO_SUSPENSE) { HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DO_SUSPENSE; KeReleaseSemaphore(&HubExtension->IdleSemaphore, LOW_REALTIME_PRIORITY, 1, FALSE); } return STATUS_PENDING; default: DPRINT1("USBH_FdoPower: Unsupported PowerState.DeviceState\n"); DbgBreakPoint(); break; } } else { if (PowerState.SystemState != PowerSystemWorking) { USBH_GetRootHubExtension(HubExtension)->SystemPowerState.SystemState = PowerState.SystemState; } if (PowerState.SystemState == PowerSystemHibernate) { HubExtension->HubFlags |= USBHUB_FDO_FLAG_HIBERNATE_STATE; } PortData = HubExtension->PortData; IsAllPortsD3 = TRUE; if (PortData && HubExtension->HubDescriptor) { for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; Port++) { PdoDevice = PortData[Port].DeviceObject; if (PdoDevice) { PortExtension = PdoDevice->DeviceExtension; if (PortExtension->CurrentPowerState.DeviceState != PowerDeviceD3) { IsAllPortsD3 = FALSE; break; } } } } if (PowerState.SystemState == PowerSystemWorking) { DevicePwrState.DeviceState = PowerDeviceD0; } else if (HubExtension->HubFlags & USBHUB_FDO_FLAG_PENDING_WAKE_IRP || !IsAllPortsD3) { DevicePwrState.DeviceState = HubExtension->DeviceState[PowerState.SystemState]; if (DevicePwrState.DeviceState == PowerDeviceUnspecified) { goto Exit; } } else { DevicePwrState.DeviceState = PowerDeviceD3; } if (DevicePwrState.DeviceState != HubExtension->CurrentPowerState.DeviceState && HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) { HubExtension->PowerIrp = Irp; IoMarkIrpPending(Irp); if (PoRequestPowerIrp(HubExtension->LowerPDO, IRP_MN_SET_POWER, DevicePwrState, USBH_FdoDeferPoRequestCompletion, (PVOID)HubExtension, NULL) == STATUS_PENDING) { return STATUS_PENDING; } IoCopyCurrentIrpStackLocationToNext(Irp); PoStartNextPowerIrp(Irp); PoCallDriver(HubExtension->LowerDevice, Irp); return STATUS_PENDING; } Exit: HubExtension->SystemPowerState.SystemState = PowerState.SystemState; if (PowerState.SystemState == PowerSystemWorking) { USBH_CheckIdleDeferred(HubExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); PoStartNextPowerIrp(Irp); return PoCallDriver(HubExtension->LowerDevice, Irp); } break; case IRP_MN_QUERY_POWER: DPRINT_PWR("USBH_FdoPower: IRP_MN_QUERY_POWER\n"); break; default: DPRINT1("USBH_FdoPower: unknown IRP_MN_POWER!\n"); break; } IoCopyCurrentIrpStackLocationToNext(Irp); PoStartNextPowerIrp(Irp); Status = PoCallDriver(HubExtension->LowerDevice, Irp); return Status; }
NTSTATUS NTAPI USBH_FdoWWIrpIoCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { PUSBHUB_FDO_EXTENSION HubExtension; NTSTATUS Status; KIRQL OldIrql; POWER_STATE PowerState; PIRP WakeIrp; DPRINT("USBH_FdoWWIrpIoCompletion: DeviceObject - %p, Irp - %p\n", DeviceObject, Irp); HubExtension = Context; Status = Irp->IoStatus.Status; IoAcquireCancelSpinLock(&OldIrql); HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_PENDING_WAKE_IRP; WakeIrp = InterlockedExchangePointer((PVOID *)&HubExtension->PendingWakeIrp, NULL); if (!InterlockedDecrement(&HubExtension->PendingRequestCount)) { KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE); } IoReleaseCancelSpinLock(OldIrql); DPRINT("USBH_FdoWWIrpIoCompletion: Status - %lX\n", Status); if (!NT_SUCCESS(Status)) { DPRINT1("USBH_FdoWWIrpIoCompletion: DbgBreakPoint() \n"); DbgBreakPoint(); } else { PowerState.DeviceState = PowerDeviceD0; HubExtension->HubFlags |= USBHUB_FDO_FLAG_WAKEUP_START; InterlockedIncrement(&HubExtension->PendingRequestCount); Status = STATUS_SUCCESS; PoRequestPowerIrp(HubExtension->LowerPDO, IRP_MN_SET_POWER, PowerState, USBH_FdoPoRequestD0Completion, (PVOID)HubExtension, NULL); } if (!WakeIrp) { if (!InterlockedExchange(&HubExtension->FdoWaitWakeLock, 1)) { Status = STATUS_MORE_PROCESSING_REQUIRED; } } DPRINT("USBH_FdoWWIrpIoCompletion: Status - %lX\n", Status); if (Status != STATUS_MORE_PROCESSING_REQUIRED) { PoStartNextPowerIrp(Irp); } return Status; }
NTSTATUS IdleNotificationRequestComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: Completion routine for idle notification irp Arguments: DeviceObject - pointer to device object Irp - I/O request packet DeviceExtension - pointer to device extension Return Value: NT status value --*/ { NTSTATUS ntStatus; POWER_STATE powerState; KIRQL oldIrql; LARGE_INTEGER dueTime; PIRP idleIrp; PUSB_IDLE_CALLBACK_INFO idleCallbackInfo; BulkUsb_DbgPrint(3, ("IdleNotificationRequestCompete - begins\n")); idleIrp = NULL; // // check the Irp status // ntStatus = Irp->IoStatus.Status; if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED) { BulkUsb_DbgPrint(1, ("Idle irp completes with error::")); switch(ntStatus) { case STATUS_INVALID_DEVICE_REQUEST: BulkUsb_DbgPrint(1, ("STATUS_INVALID_DEVICE_REQUEST\n")); break; case STATUS_CANCELLED: BulkUsb_DbgPrint(1, ("STATUS_CANCELLED\n")); break; case STATUS_POWER_STATE_INVALID: BulkUsb_DbgPrint(1, ("STATUS_POWER_STATE_INVALID\n")); goto IdleNotificationRequestComplete_Exit; case STATUS_DEVICE_BUSY: BulkUsb_DbgPrint(1, ("STATUS_DEVICE_BUSY\n")); break; default: BulkUsb_DbgPrint(1, ("default: status = %X\n", ntStatus)); break; } // // if in error, issue a SetD0 // BulkUsb_DbgPrint(3, ("IdleNotificationRequestComplete::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc, DeviceExtension, NULL); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("PoRequestPowerIrp failed\n")); } } IdleNotificationRequestComplete_Exit: KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql); idleCallbackInfo = DeviceExtension->IdleCallbackInfo; DeviceExtension->IdleCallbackInfo = NULL; idleIrp = (PIRP) InterlockedExchangePointer( &DeviceExtension->PendingIdleIrp, NULL); InterlockedExchange(&DeviceExtension->IdleReqPend, 0); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); if(idleCallbackInfo) { ExFreePool(idleCallbackInfo); } // // since the irp was created using IoAllocateIrp, // the Irp needs to be freed using IoFreeIrp. // Also return STATUS_MORE_PROCESSING_REQUIRED so that // the kernel does not reference this in the near future. // if(idleIrp) { BulkUsb_DbgPrint(3, ("completion routine has a valid irp and frees it\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } else { // // The CancelSelectiveSuspend routine has grabbed the Irp from the device // extension. Now the last one to decrement the FreeIdleIrpCount should // free the irp. // if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) { BulkUsb_DbgPrint(3, ("completion routine frees the irp\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } } if(DeviceExtension->SSEnable) { BulkUsb_DbgPrint(3, ("Set the timer to fire DPCs\n")); dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms KeSetTimerEx(&DeviceExtension->Timer, dueTime, IDLE_INTERVAL, // 5000 ms &DeviceExtension->DeferredProcCall); BulkUsb_DbgPrint(3, ("IdleNotificationRequestCompete - ends\n")); } return STATUS_MORE_PROCESSING_REQUIRED; }
static NTSTATUS IdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PTDeviceExtension DeviceExtension) { NTSTATUS ntStatus; POWER_STATE powerState; KIRQL oldIrql; LARGE_INTEGER dueTime; PIRP idleIrp; PUSB_IDLE_CALLBACK_INFO idleCallbackInfo; BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestCompete - begins\n")); idleIrp = NULL; ntStatus = Irp->IoStatus.Status; if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED) { BulkUsb_DbgPrint(1, ("file bulkdev: Idle irp completes with error::")); switch(ntStatus) { case STATUS_INVALID_DEVICE_REQUEST: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_INVALID_DEVICE_REQUEST\n")); break; case STATUS_CANCELLED: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_CANCELLED\n")); break; case STATUS_POWER_STATE_INVALID: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_POWER_STATE_INVALID\n")); goto IdleNotificationRequestComplete_Exit; case STATUS_DEVICE_BUSY: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_DEVICE_BUSY\n")); break; default: BulkUsb_DbgPrint(1, ("file bulkdev: default: status = %X\n", ntStatus)); break; } if(PowerDeviceD0 != DeviceExtension->DevPower) { BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestComplete::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc, DeviceExtension, NULL); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("file bulkdev: PoRequestPowerIrp failed\n")); } } } IdleNotificationRequestComplete_Exit: KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql); idleCallbackInfo = DeviceExtension->IdleCallbackInfo; DeviceExtension->IdleCallbackInfo = NULL; idleIrp = (PIRP) InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL); InterlockedExchange(&DeviceExtension->IdleReqPend, 0); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); if(idleCallbackInfo) { ExFreePool(idleCallbackInfo); } if(idleIrp) { BulkUsb_DbgPrint(3, ("file bulkdev: completion routine has a valid irp and frees it\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } else { if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) { BulkUsb_DbgPrint(3, ("file bulkdev: completion routine frees the irp\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } } if(DeviceExtension->SSEnable) { BulkUsb_DbgPrint(3, ("file bulkdev: Set the timer to fire DPCs\n")); dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms KeSetTimerEx(&DeviceExtension->Timer, dueTime, IDLE_INTERVAL, // 5000 ms &DeviceExtension->DeferredProcCall); BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestCompete - ends\n")); } return STATUS_MORE_PROCESSING_REQUIRED; }
VOID IdleNotificationCallback( IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: "A pointer to a callback function in your driver is passed down the stack with this IOCTL, and it is this callback function that is called by USBHUB when it safe for your device to power down." "When the callback in your driver is called, all you really need to do is to to first ensure that a WaitWake Irp has been submitted for your device, if remote wake is possible for your device and then request a SetD2 (or DeviceWake)" Arguments: DeviceExtension - pointer to device extension Return Value: NT status value --*/ { NTSTATUS ntStatus; POWER_STATE powerState; KEVENT irpCompletionEvent; PIRP_COMPLETION_CONTEXT irpContext; BulkUsb_DbgPrint(3, ("IdleNotificationCallback - begins\n")); // // Dont idle, if the device was just disconnected or being stopped // i.e. return for the following DeviceState(s) // NotStarted, Stopped, PendingStop, PendingRemove, SurpriseRemoved, Removed // if(DeviceExtension->DeviceState != Working) { return; } // // If there is not already a WW IRP pending, submit one now // if(DeviceExtension->WaitWakeEnable) { IssueWaitWake(DeviceExtension); } // // power down the device // irpContext = (PIRP_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(IRP_COMPLETION_CONTEXT)); if(!irpContext) { BulkUsb_DbgPrint(1, ("Failed to alloc memory for irpContext\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } else { // // increment the count. In the HoldIoRequestWorkerRoutine, the // count is decremented twice (one for the system Irp and the // other for the device Irp. An increment here compensates for // the sytem irp..The decrement corresponding to this increment // is in the completion function // BulkUsb_DbgPrint(3, ("IdleNotificationCallback::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = DeviceExtension->PowerDownLevel; KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE); irpContext->DeviceExtension = DeviceExtension; irpContext->Event = &irpCompletionEvent; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc, irpContext, NULL); if(STATUS_PENDING == ntStatus) { BulkUsb_DbgPrint(3, ("IdleNotificationCallback::" "waiting for the power irp to complete\n")); KeWaitForSingleObject(&irpCompletionEvent, Executive, KernelMode, FALSE, NULL); } } if(!NT_SUCCESS(ntStatus)) { if(irpContext) { ExFreePool(irpContext); } } BulkUsb_DbgPrint(3, ("IdleNotificationCallback - ends\n")); }
NTSTATUS NTAPI PortClsPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStack; PPCLASS_DEVICE_EXTENSION DeviceExtension; PQUERY_POWER_CONTEXT PwrContext; POWER_STATE PowerState; NTSTATUS Status = STATUS_SUCCESS; DPRINT("PortClsPower called\n"); // get currrent stack location IoStack = IoGetCurrentIrpStackLocation(Irp); if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER) { // just forward the request Status = PcForwardIrpSynchronous(DeviceObject, Irp); // start next power irp PoStartNextPowerIrp(Irp); // complete request Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); // done return Status; } // get device extension DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension; // get current request type if (IoStack->Parameters.Power.Type == DevicePowerState) { // request for device power state if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState) { // nothing has changed if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) { // only forward query requests Status = PcForwardIrpSynchronous(DeviceObject, Irp); } // start next power irp PoStartNextPowerIrp(Irp); // complete request Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); // done return Status; } if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) { // check if there is a registered adapter power management if (DeviceExtension->AdapterPowerManagement) { // it is query if the change can be changed PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState); Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState); // sanity check PC_ASSERT(Status == STATUS_SUCCESS); } // only forward query requests PcForwardIrpSynchronous(DeviceObject, Irp); // start next power irp PoStartNextPowerIrp(Irp); // complete request Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); // done return Status; } else { // set power state PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState); PoSetPowerState(DeviceObject, DevicePowerState, PowerState); // check if there is a registered adapter power management if (DeviceExtension->AdapterPowerManagement) { // notify of a power change state DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState); } // FIXME call all registered IPowerNotify interfaces via ISubdevice interface // store new power state DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState; // complete request Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); // done return Status; } } else { // sanity check PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState); if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) { // mark irp as pending IoMarkIrpPending(Irp); // allocate power completion context PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS); if (!PwrContext) { // no memory PoStartNextPowerIrp(Irp); // complete and forget Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; IoCompleteRequest(Irp, IO_NO_INCREMENT); // done return Status; } // setup power context PwrContext->Irp = Irp; PwrContext->DeviceObject = DeviceObject; // pass the irp down PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState); Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL); // check for success if (!NT_SUCCESS(Status)) { // failed Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); // done return Status; } // done return STATUS_PENDING; } else { // set power request DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState; // only forward query requests Status = PcForwardIrpSynchronous(DeviceObject, Irp); // start next power irp PoStartNextPowerIrp(Irp); // complete request Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); // done return Status; } } }
VOID SendDeviceIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp ) /*++ Routine Description: This routine is invoked from the completion routine of the system power irp. This routine will PoRequest a device power irp. The system irp is passed as a context to the the device power irp. Arguments: DeviceObject - pointer to device object SIrp - system power irp. Return Value: None --*/ { NTSTATUS ntStatus; POWER_STATE powState; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; SYSTEM_POWER_STATE systemState; DEVICE_POWER_STATE devState; PPOWER_COMPLETION_CONTEXT powerContext; // // initialize variables // irpStack = IoGetCurrentIrpStackLocation(SIrp); systemState = irpStack->Parameters.Power.State.SystemState; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; MobiUsb_DbgPrint(3, ("file mobipwr: SendDeviceIrp - begins\n")); // // Read out the D-IRP out of the S->D mapping array captured in QueryCap's. // we can choose deeper sleep states than our mapping but never choose // lighter ones. // devState = deviceExtension->DeviceCapabilities.DeviceState[systemState]; powState.DeviceState = devState; powerContext = (PPOWER_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT)); if(!powerContext) { MobiUsb_DbgPrint(1, ("file mobipwr: Failed to alloc memory for powerContext\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } else { powerContext->DeviceObject = DeviceObject; powerContext->SIrp = SIrp; // // in win2k PoRequestPowerIrp can take fdo or pdo. // ntStatus = PoRequestPowerIrp( deviceExtension->PhysicalDeviceObject, irpStack->MinorFunction, powState, (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine, powerContext, NULL); } if(!NT_SUCCESS(ntStatus)) { if(powerContext) { ExFreePool(powerContext); } PoStartNextPowerIrp(SIrp); SIrp->IoStatus.Status = ntStatus; SIrp->IoStatus.Information = 0; IoCompleteRequest(SIrp, IO_NO_INCREMENT); MobiUsb_DbgPrint(3, ("file mobipwr: SendDeviceIrp::")); MobiUsb_IoDecrement(deviceExtension); } MobiUsb_DbgPrint(3, ("file mobipwr: SendDeviceIrp - ends\n")); }
VOID WaitWakeCallback( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) /*++ Routine Description: This is the PoRequest completion routine for the wait wake irp. Arguments: DeviceObject - pointer to device object MinorFunction - irp minor function PowerState - power state of the irp. Context - context passed to the completion routine. IoStatus - status block. Return Value: None --*/ { NTSTATUS ntStatus; POWER_STATE powerState; PDEVICE_EXTENSION deviceExtension; MobiUsb_DbgPrint(3, ("file mobipwr: WaitWakeCallback - begins\n")); deviceExtension = (PDEVICE_EXTENSION) Context; InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0); if(!NT_SUCCESS(IoStatus->Status)) { return; } // // wake up the device // if(deviceExtension->DevPower == PowerDeviceD0) { MobiUsb_DbgPrint(3, ("file mobipwr: device already powered up...\n")); return; } MobiUsb_DbgPrint(3, ("file mobipwr: WaitWakeCallback::")); MobiUsb_IoIncrement(deviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc, deviceExtension, NULL); if(deviceExtension->WaitWakeEnable) { IssueWaitWake(deviceExtension); } MobiUsb_DbgPrint(3, ("file mobipwr: WaitWakeCallback - ends\n")); return; }
NTSTATUS t1394Cmdr_SystemSetPowerIrpCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID NotUsed ) { PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; NTSTATUS ntStatus = Irp->IoStatus.Status; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); POWER_STATE state = stack->Parameters.Power.State; POWER_COMPLETION_CONTEXT *powerContext = NULL; PIRP pDIrp = NULL; ENTER("t1394Cmdr_SystemPowerIrpCompletion"); if (!NT_SUCCESS(ntStatus)) { TRACE(TL_TRACE, ("Set System Power Irp failed, status = 0x%x\n", ntStatus)); PoStartNextPowerIrp(Irp); ntStatus = STATUS_SUCCESS; goto Exit_SystemSetPowerIrpCompletion; } // allocate powerContext powerContext = (POWER_COMPLETION_CONTEXT*) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT)); if (!powerContext) { TRACE(TL_TRACE, ("Failed to allocate powerContext, status = 0x%x\n", ntStatus)); ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto Exit_SystemSetPowerIrpCompletion; } else { if (state.SystemState == PowerSystemWorking) { state.DeviceState = PowerDeviceD0; } else { state.DeviceState = PowerDeviceD3; } powerContext->DeviceObject = DeviceObject; powerContext->SIrp = Irp; ntStatus = PoRequestPowerIrp(deviceExtension->StackDeviceObject, IRP_MN_SET_POWER, state, t1394Cmdr_DeviceSetPowerIrpCompletion, powerContext, &pDIrp); TRACE(TL_TRACE, ("New Device Set Power Irp = 0x%x\n", pDIrp)); } Exit_SystemSetPowerIrpCompletion: if (!NT_SUCCESS(ntStatus)) { TRACE(TL_TRACE, ("System SetPowerIrp Completion routine failed = 0x%x\n", ntStatus)); if (powerContext) { ExFreePool(powerContext); } PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus; } else { ntStatus = STATUS_MORE_PROCESSING_REQUIRED; } EXIT("t1394Cmdr_SystemPowerIrpCompletion", ntStatus); return ntStatus; }