mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 02:13:29 +00:00
709 lines
20 KiB
C
709 lines
20 KiB
C
/*
|
|
* PROJECT: ReactOS USB Port Driver
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: USBPort power handling functions
|
|
* COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
|
|
*/
|
|
|
|
#include "usbport.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_CompletePdoWaitWake(IN PDEVICE_OBJECT FdoDevice)
|
|
{
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PIRP Irp;
|
|
KIRQL OldIrql;
|
|
|
|
DPRINT("USBPORT_CompletePdoWaitWake: ... \n");
|
|
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
PdoDevice = FdoExtension->RootHubPdo;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
|
|
KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
|
|
|
|
Irp = PdoExtension->WakeIrp;
|
|
|
|
if (Irp && IoSetCancelRoutine(Irp, NULL))
|
|
{
|
|
PdoExtension->WakeIrp = NULL;
|
|
KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
|
|
|
|
DPRINT("USBPORT_CompletePdoWaitWake: Complete Irp - %p\n", Irp);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return;
|
|
}
|
|
|
|
KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_HcWakeDpc(IN PRKDPC Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SystemArgument1,
|
|
IN PVOID SystemArgument2)
|
|
{
|
|
DPRINT("USBPORT_HcWakeDpc: ... \n");
|
|
USBPORT_CompletePdoWaitWake((PDEVICE_OBJECT)DeferredContext);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_HcQueueWakeDpc(IN PDEVICE_OBJECT FdoDevice)
|
|
{
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
|
|
DPRINT("USBPORT_HcQueueWakeDpc: ... \n");
|
|
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
KeInsertQueueDpc(&FdoExtension->HcWakeDpc, NULL, NULL);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_CompletePendingIdleIrp(IN PDEVICE_OBJECT PdoDevice)
|
|
{
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PIRP Irp;
|
|
|
|
DPRINT("USBPORT_CompletePendingIdleIrp: ... \n");
|
|
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
|
|
Irp = IoCsqRemoveNextIrp(&FdoExtension->IdleIoCsq, 0);
|
|
|
|
if (Irp)
|
|
{
|
|
InterlockedDecrement(&FdoExtension->IdleLockCounter);
|
|
|
|
DPRINT("USBPORT_CompletePendingIdleIrp: Complete Irp - %p\n", Irp);
|
|
|
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_DoSetPowerD0(IN PDEVICE_OBJECT FdoDevice)
|
|
{
|
|
DPRINT("USBPORT_DoSetPowerD0: FIXME!\n");
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_SuspendController(IN PDEVICE_OBJECT FdoDevice)
|
|
{
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PUSBPORT_REGISTRATION_PACKET Packet;
|
|
|
|
DPRINT1("USBPORT_SuspendController \n");
|
|
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
Packet = &FdoExtension->MiniPortInterface->Packet;
|
|
|
|
FdoExtension->TimerFlags |= USBPORT_TMFLAG_RH_SUSPENDED;
|
|
|
|
USBPORT_FlushController(FdoDevice);
|
|
|
|
if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FdoExtension->TimerFlags |= USBPORT_TMFLAG_HC_SUSPENDED;
|
|
|
|
if (FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
|
|
{
|
|
FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_SUSPENDED;
|
|
|
|
USBPORT_Wait(FdoDevice, 10);
|
|
Packet->SuspendController(FdoExtension->MiniPortExt);
|
|
}
|
|
|
|
FdoExtension->Flags |= USBPORT_FLAG_HC_SUSPEND;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_ResumeController(IN PDEVICE_OBJECT FdoDevice)
|
|
{
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PUSBPORT_REGISTRATION_PACKET Packet;
|
|
KIRQL OldIrql;
|
|
MPSTATUS MpStatus;
|
|
|
|
DPRINT1("USBPORT_ResumeController: ... \n");
|
|
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
Packet = &FdoExtension->MiniPortInterface->Packet;
|
|
|
|
if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
|
|
|
|
FdoExtension->TimerFlags &= ~(USBPORT_TMFLAG_HC_SUSPENDED |
|
|
USBPORT_TMFLAG_RH_SUSPENDED);
|
|
|
|
KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
|
|
|
|
if (!(FdoExtension->MiniPortFlags & USBPORT_MPFLAG_SUSPENDED))
|
|
{
|
|
FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
|
|
return Status;
|
|
}
|
|
|
|
FdoExtension->MiniPortFlags &= ~USBPORT_MPFLAG_SUSPENDED;
|
|
|
|
if (!Packet->ResumeController(FdoExtension->MiniPortExt))
|
|
{
|
|
Status = USBPORT_Wait(FdoDevice, 100);
|
|
|
|
FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
|
|
return Status;
|
|
}
|
|
|
|
KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
|
|
FdoExtension->TimerFlags |= (USBPORT_TMFLAG_HC_SUSPENDED |
|
|
USBPORT_TMFLAG_HC_RESUME);
|
|
KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
|
|
|
|
USBPORT_MiniportInterrupts(FdoDevice, FALSE);
|
|
|
|
Packet->StopController(FdoExtension->MiniPortExt, 1);
|
|
|
|
USBPORT_NukeAllEndpoints(FdoDevice);
|
|
|
|
RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize);
|
|
|
|
RtlZeroMemory((PVOID)FdoExtension->UsbPortResources.StartVA,
|
|
Packet->MiniPortResourcesSize);
|
|
|
|
FdoExtension->UsbPortResources.IsChirpHandled = TRUE;
|
|
|
|
MpStatus = Packet->StartController(FdoExtension->MiniPortExt,
|
|
&FdoExtension->UsbPortResources);
|
|
|
|
FdoExtension->UsbPortResources.IsChirpHandled = FALSE;
|
|
|
|
if (!MpStatus)
|
|
{
|
|
USBPORT_MiniportInterrupts(FdoDevice, TRUE);
|
|
}
|
|
|
|
KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
|
|
|
|
FdoExtension->TimerFlags &= ~(USBPORT_TMFLAG_HC_SUSPENDED |
|
|
USBPORT_TMFLAG_HC_RESUME |
|
|
USBPORT_TMFLAG_RH_SUSPENDED);
|
|
|
|
KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
|
|
|
|
Status = USBPORT_Wait(FdoDevice, 100);
|
|
|
|
FdoExtension->Flags &= ~USBPORT_FLAG_HC_SUSPEND;
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_PdoDevicePowerState(IN PDEVICE_OBJECT PdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PIO_STACK_LOCATION IoStack;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
POWER_STATE State;
|
|
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
State = IoStack->Parameters.Power.State;
|
|
|
|
DPRINT1("USBPORT_PdoDevicePowerState: Irp - %p, State - %x\n",
|
|
Irp,
|
|
State.DeviceState);
|
|
|
|
if (State.DeviceState == PowerDeviceD0)
|
|
{
|
|
if (FdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0)
|
|
{
|
|
// FIXME FdoExtension->Flags
|
|
while (FdoExtension->SetPowerLockCounter)
|
|
{
|
|
USBPORT_Wait(FdoDevice, 10);
|
|
}
|
|
|
|
USBPORT_ResumeController(FdoDevice);
|
|
|
|
PdoExtension->CommonExtension.DevicePowerState = PowerDeviceD0;
|
|
|
|
USBPORT_CompletePdoWaitWake(FdoDevice);
|
|
USBPORT_CompletePendingIdleIrp(PdoDevice);
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("USBPORT_PdoDevicePowerState: FdoExtension->Flags - %lx\n",
|
|
FdoExtension->Flags);
|
|
|
|
DbgBreakPoint();
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
}
|
|
else if (State.DeviceState == PowerDeviceD1 ||
|
|
State.DeviceState == PowerDeviceD2 ||
|
|
State.DeviceState == PowerDeviceD3)
|
|
{
|
|
FdoExtension->TimerFlags |= USBPORT_TMFLAG_WAKE;
|
|
USBPORT_SuspendController(FdoDevice);
|
|
PdoExtension->CommonExtension.DevicePowerState = State.DeviceState;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_CancelPendingWakeIrp(IN PDEVICE_OBJECT PdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
KIRQL OldIrql;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
|
|
DPRINT("USBPORT_CancelPendingWakeIrp: ... \n");
|
|
|
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoExtension = PdoExtension->FdoDevice->DeviceExtension;
|
|
|
|
KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
|
|
|
|
if (PdoExtension->WakeIrp == Irp)
|
|
{
|
|
PdoExtension->WakeIrp = NULL;
|
|
}
|
|
|
|
KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
|
|
|
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_PdoPower(IN PDEVICE_OBJECT PdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PIO_STACK_LOCATION IoStack;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
NTSTATUS Status;
|
|
KIRQL OldIrql;
|
|
|
|
DPRINT("USBPORT_PdoPower: Irp - %p\n", Irp);
|
|
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
switch (IoStack->MinorFunction)
|
|
{
|
|
case IRP_MN_WAIT_WAKE:
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE\n");
|
|
|
|
if (!(FdoExtension->Flags & USBPORT_FLAG_HC_STARTED))
|
|
{
|
|
/* The device does not support wake-up */
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
KeAcquireSpinLock(&FdoExtension->PowerWakeSpinLock, &OldIrql);
|
|
|
|
IoSetCancelRoutine(Irp, USBPORT_CancelPendingWakeIrp);
|
|
|
|
/* Check if the IRP has been cancelled */
|
|
if (Irp->Cancel)
|
|
{
|
|
if (IoSetCancelRoutine(Irp, NULL))
|
|
{
|
|
/* IRP has been cancelled, release cancel spinlock */
|
|
KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
|
|
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - STATUS_CANCELLED\n");
|
|
|
|
/* IRP is cancelled */
|
|
Status = STATUS_CANCELLED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!PdoExtension->WakeIrp)
|
|
{
|
|
/* The driver received the IRP
|
|
and is waiting for the device to signal wake-up. */
|
|
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - No WakeIrp\n");
|
|
|
|
IoMarkIrpPending(Irp);
|
|
PdoExtension->WakeIrp = Irp;
|
|
|
|
KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
|
|
return STATUS_PENDING;
|
|
}
|
|
else
|
|
{
|
|
/* An IRP_MN_WAIT_WAKE request is already pending and must be
|
|
completed or canceled before another IRP_MN_WAIT_WAKE request
|
|
can be issued. */
|
|
|
|
if (IoSetCancelRoutine(Irp, NULL))
|
|
{
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_WAIT_WAKE - STATUS_DEVICE_BUSY\n");
|
|
|
|
KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
|
|
PoStartNextPowerIrp(Irp);
|
|
Status = STATUS_DEVICE_BUSY;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(FALSE);
|
|
KeReleaseSpinLock(&FdoExtension->PowerWakeSpinLock, OldIrql);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
case IRP_MN_POWER_SEQUENCE:
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_POWER_SEQUENCE\n");
|
|
PoStartNextPowerIrp(Irp);
|
|
break;
|
|
|
|
case IRP_MN_SET_POWER:
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER\n");
|
|
|
|
if (IoStack->Parameters.Power.Type == DevicePowerState)
|
|
{
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER/DevicePowerState\n");
|
|
Status = USBPORT_PdoDevicePowerState(PdoDevice, Irp);
|
|
PoStartNextPowerIrp(Irp);
|
|
break;
|
|
}
|
|
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_SET_POWER/SystemPowerState \n");
|
|
|
|
if (IoStack->Parameters.Power.State.SystemState == PowerSystemWorking)
|
|
{
|
|
FdoExtension->TimerFlags |= USBPORT_TMFLAG_WAKE;
|
|
}
|
|
else
|
|
{
|
|
FdoExtension->TimerFlags &= ~USBPORT_TMFLAG_WAKE;
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
PoStartNextPowerIrp(Irp);
|
|
break;
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
DPRINT("USBPORT_PdoPower: IRP_MN_QUERY_POWER\n");
|
|
Status = STATUS_SUCCESS;
|
|
PoStartNextPowerIrp(Irp);
|
|
break;
|
|
|
|
default:
|
|
DPRINT1("USBPORT_PdoPower: unknown IRP_MN_POWER!\n");
|
|
PoStartNextPowerIrp(Irp);
|
|
break;
|
|
}
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_HcWake(IN PDEVICE_OBJECT FdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
DPRINT1("USBPORT_HcWake: UNIMPLEMENTED. FIXME. \n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_DevicePowerState(IN PDEVICE_OBJECT FdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
DPRINT1("USBPORT_DevicePowerState: UNIMPLEMENTED. FIXME. \n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_SystemPowerState(IN PDEVICE_OBJECT FdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
DPRINT1("USBPORT_SystemPowerState: UNIMPLEMENTED. FIXME. \n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_FdoPower(IN PDEVICE_OBJECT FdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PIO_STACK_LOCATION IoStack;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("USBPORT_FdoPower: ... \n");
|
|
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
switch (IoStack->MinorFunction)
|
|
{
|
|
case IRP_MN_WAIT_WAKE:
|
|
DPRINT("USBPORT_FdoPower: IRP_MN_WAIT_WAKE\n");
|
|
Status = USBPORT_HcWake(FdoDevice, Irp);
|
|
return Status;
|
|
|
|
case IRP_MN_POWER_SEQUENCE:
|
|
DPRINT("USBPORT_FdoPower: IRP_MN_POWER_SEQUENCE\n");
|
|
break;
|
|
|
|
case IRP_MN_SET_POWER:
|
|
DPRINT("USBPORT_FdoPower: IRP_MN_SET_POWER\n");
|
|
if (IoStack->Parameters.Power.Type == DevicePowerState)
|
|
{
|
|
Status = USBPORT_DevicePowerState(FdoDevice, Irp);
|
|
}
|
|
else
|
|
{
|
|
Status = USBPORT_SystemPowerState(FdoDevice, Irp);
|
|
}
|
|
|
|
if (Status != STATUS_PENDING)
|
|
break;
|
|
|
|
return Status;
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
DPRINT("USBPORT_FdoPower: IRP_MN_QUERY_POWER\n");
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
DPRINT1("USBPORT_FdoPower: unknown IRP_MN_POWER!\n");
|
|
break;
|
|
}
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
PoStartNextPowerIrp(Irp);
|
|
return PoCallDriver(FdoExtension->CommonExtension.LowerDevice, Irp);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_DoIdleNotificationCallback(IN PVOID Context)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PIRP NextIrp;
|
|
LARGE_INTEGER CurrentTime = {{0, 0}};
|
|
PTIMER_WORK_QUEUE_ITEM IdleQueueItem;
|
|
PDEVICE_OBJECT PdoDevice;
|
|
PUSB_IDLE_CALLBACK_INFO IdleCallbackInfo;
|
|
KIRQL OldIrql;
|
|
|
|
DPRINT("USBPORT_DoIdleNotificationCallback \n");
|
|
|
|
IdleQueueItem = Context;
|
|
|
|
FdoDevice = IdleQueueItem->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
PdoDevice = FdoExtension->RootHubPdo;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
|
|
KeQuerySystemTime(&CurrentTime);
|
|
|
|
if ((FdoExtension->IdleTime.QuadPart == 0) ||
|
|
(((CurrentTime.QuadPart - FdoExtension->IdleTime.QuadPart) / 10000) >= 500))
|
|
{
|
|
if (PdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0 &&
|
|
FdoExtension->CommonExtension.DevicePowerState == PowerDeviceD0)
|
|
{
|
|
NextIrp = IoCsqRemoveNextIrp(&FdoExtension->IdleIoCsq, NULL);
|
|
|
|
if (NextIrp)
|
|
{
|
|
IoStack = IoGetCurrentIrpStackLocation(NextIrp);
|
|
IdleCallbackInfo = IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
|
|
|
if (IdleCallbackInfo && IdleCallbackInfo->IdleCallback)
|
|
{
|
|
IdleCallbackInfo->IdleCallback(IdleCallbackInfo->IdleContext);
|
|
}
|
|
|
|
if (NextIrp->Cancel)
|
|
{
|
|
InterlockedDecrement(&FdoExtension->IdleLockCounter);
|
|
|
|
NextIrp->IoStatus.Status = STATUS_CANCELLED;
|
|
NextIrp->IoStatus.Information = 0;
|
|
IoCompleteRequest(NextIrp, IO_NO_INCREMENT);
|
|
}
|
|
else
|
|
{
|
|
IoCsqInsertIrp(&FdoExtension->IdleIoCsq, NextIrp, NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &OldIrql);
|
|
FdoExtension->TimerFlags &= ~USBPORT_TMFLAG_IDLE_QUEUEITEM_ON;
|
|
KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, OldIrql);
|
|
|
|
ExFreePoolWithTag(IdleQueueItem, USB_PORT_TAG);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
USBPORT_IdleNotification(IN PDEVICE_OBJECT PdoDevice,
|
|
IN PIRP Irp)
|
|
{
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_OBJECT FdoDevice;
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
LONG LockCounter;
|
|
NTSTATUS Status = STATUS_PENDING;
|
|
|
|
DPRINT("USBPORT_IdleNotification: Irp - %p\n", Irp);
|
|
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
FdoDevice = PdoExtension->FdoDevice;
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
|
|
LockCounter = InterlockedIncrement(&FdoExtension->IdleLockCounter);
|
|
|
|
if (LockCounter != 0)
|
|
{
|
|
if (Status != STATUS_PENDING)
|
|
{
|
|
InterlockedDecrement(&FdoExtension->IdleLockCounter);
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
Status = STATUS_DEVICE_BUSY;
|
|
}
|
|
|
|
if (Status != STATUS_PENDING)
|
|
{
|
|
InterlockedDecrement(&FdoExtension->IdleLockCounter);
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
Irp->IoStatus.Status = STATUS_PENDING;
|
|
IoMarkIrpPending(Irp);
|
|
|
|
KeQuerySystemTime(&FdoExtension->IdleTime);
|
|
|
|
IoCsqInsertIrp(&FdoExtension->IdleIoCsq, Irp, 0);
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
USBPORT_AdjustDeviceCapabilities(IN PDEVICE_OBJECT FdoDevice,
|
|
IN PDEVICE_OBJECT PdoDevice)
|
|
{
|
|
PUSBPORT_DEVICE_EXTENSION FdoExtension;
|
|
PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
|
|
PDEVICE_CAPABILITIES Capabilities;
|
|
|
|
DPRINT("USBPORT_AdjustDeviceCapabilities: ... \n");
|
|
|
|
FdoExtension = FdoDevice->DeviceExtension;
|
|
PdoExtension = PdoDevice->DeviceExtension;
|
|
Capabilities = &PdoExtension->Capabilities;
|
|
|
|
RtlCopyMemory(Capabilities,
|
|
&FdoExtension->Capabilities,
|
|
sizeof(DEVICE_CAPABILITIES));
|
|
|
|
Capabilities->DeviceD1 = FALSE;
|
|
Capabilities->DeviceD2 = TRUE;
|
|
|
|
Capabilities->Removable = FALSE;
|
|
Capabilities->UniqueID = FALSE;
|
|
|
|
Capabilities->WakeFromD0 = TRUE;
|
|
Capabilities->WakeFromD1 = FALSE;
|
|
Capabilities->WakeFromD2 = TRUE;
|
|
Capabilities->WakeFromD3 = FALSE;
|
|
|
|
Capabilities->Address = 0;
|
|
Capabilities->UINumber = 0;
|
|
|
|
if (Capabilities->SystemWake == PowerSystemUnspecified)
|
|
Capabilities->SystemWake = PowerSystemWorking;
|
|
|
|
Capabilities->DeviceWake = PowerDeviceD2;
|
|
|
|
Capabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
|
|
Capabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
|
|
Capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
|
|
Capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
|
|
}
|