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

📄 usbfx2lk_selsusp.cpp

📁 基于vc++6.0环境的cypress USB 驱动源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:

    //
    // Setup the power up state to be D0
    //
    devicePowerState.DeviceState = PowerDeviceD0;

    //
    // Initialize the power up event that our power completion
    //  routine will signal when the power up is complete
    //
    KeInitializeEvent(&powerUpCompleteEvent, NotificationEvent, FALSE);

    //
    // And ask the power manager to create and send a power up D-IRP 
    //  to our PDO. Specify the synchronous power completion routine,
    //  which will simply set the event that we pass to it when it
    //  runs
    //
    status = PoRequestPowerIrp(DevExt->PhysicalDeviceObject, 
                               IRP_MN_SET_POWER, 
                               devicePowerState, 
                               SSSynchronousPowerIrpCompletionFunc,
                               &powerUpCompleteEvent, 
                               NULL);

    //
    // We want to do this operation synchronously, so just wait
    //  for the operation to complete
    //
    if (status == STATUS_PENDING) {

        OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
                ("SSPowerUpDevice: Waiting for the power irp to complete\n"));

        OsrWaitForSingleObject(&powerUpCompleteEvent);
    }

    //
    // The I/O is finished.
    //
    OsrDecrementOutstandingIoCount(DevExt,__FILE__,__LINE__);

    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
        ("SSPowerUpDevice: PoRequestPowerIrp returned 0x%x (%s).\n",
                status,OsrNtStatusToString(status)));

    //
    // A power up is complete, get the Selective Suspend
    //  state properly updated
    //
    SSPowerUpCompleteUpdateSSState(DevExt);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
                                    ("SSPowerUpDevice: Exited\n"));
    
}


///////////////////////////////////////////////////////////////////////////////
//
// SSPowerUpCompleteUpdateSSState
//
//      This routine updates the Selective Suspend state of the device 
//      after a power up operation is complete
//
//  INPUTS:
//
//      DevExt  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL <= DISPATCH_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID SSPowerUpCompleteUpdateSSState(PUSBFX2LK_EXT DevExt) 
{
    KIRQL oldIrql;

    //
    // If someone has called here then we've just finished 
    //  a power up so we need to update the SS state
    //  based on whether or not the power up actually
    //  happened
    //
    KeAcquireSpinLock(&DevExt->SSLock,&oldIrql);
    
    if (DevExt->DevicePowerState != PowerDeviceD0) {

        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_SELECTIVE_SUSPEND,
           ("SSPowerUpDevice: Power up of device did not succeed. Device "\
                                                    "power state is 0x%x\n",
           DevExt->DevicePowerState));

        //
        // Indicate that we're suspended.
        //
        DevExt->SSState = SS_SUSPENDED;

    } else {

        //
        // Device is now powered up!
        //
        DevExt->SSState = SS_NOT_STARTED;

    }

    //
    // Set the "device is now out of selective suspend" event
    //
    KeSetEvent(&DevExt->SSDeviceNotSuspendedEvent, 
               EVENT_INCREMENT,
               FALSE);

    KeReleaseSpinLock(&DevExt->SSLock,oldIrql);

    //
    // Restart any requests that may have been queued
    //  while the device was powering down.
    //
    OsrProcessQueuedRequests(DevExt);

}



///////////////////////////////////////////////////////////////////////////////
//
// SSPowerUpDeviceAsync
//
//      This routine asynchronously powers up the device
//
//  INPUTS:
//
//      DevExt  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID SSPowerUpDeviceAsync(PUSBFX2LK_EXT DevExt) 
{

    POWER_STATE devicePowerState;
    NTSTATUS status;
    KIRQL oldIrql;

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
                                ("SSPowerUpDeviceAsync: Entered\n"));

    //
    // We should not already be in D0 at this point
    //
    ASSERT(DevExt->DevicePowerState != PowerDeviceD0);

    //
    // Submit a device power IRP to our device
    //

    //
    // This constitutes a new I/O on the device, 
    //  so bump the oustanding I/O count
    //
    OsrIncrementOutstandingIoCount(DevExt,__FILE__,__LINE__);

    //
    // Setup the power up state to be D0
    //
    devicePowerState.DeviceState = PowerDeviceD0;

    //
    // And ask the power manager to create and send a power up D-IRP 
    //  to our PDO. Specify the asynchronous power completion routine
    //  which will deal with getting the SS state updated when the 
    //  IRP is completed.
    //
    status = PoRequestPowerIrp(DevExt->PhysicalDeviceObject, 
                               IRP_MN_SET_POWER, 
                               devicePowerState, 
                               SSAsynchronousPowerUpIrpCompletionFunc,
                               DevExt, 
                               NULL);

    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
        ("SSPowerUpDeviceAsync: PoRequestPowerIrp returned 0x%x (%s).\n",
                status,OsrNtStatusToString(status)));

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
                                    ("SSPowerUpDeviceAsync: Exited\n"));
    
}



///////////////////////////////////////////////////////////////////////////////
//
// SSSuspendDevice
//
//      This routine synchronously suspends the device
//
//  INPUTS:
//
//      DevExt  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID SSSuspendDevice(PUSBFX2LK_EXT DevExt) 
{

    POWER_STATE devicePowerState;
    KEVENT powerDownCompleteEvent;
    NTSTATUS status;

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
                                    ("SSSuspendDevice: Entered\n"));

    //
    // If we haven't figured out the power state
    //  that we're going to suspend to then we can't
    //  suspend. This may happen while the device is first starting
    //  up.
    //
    // Also, if we're already powered down there's no point in 
    //  trying to power down again. 
    //
    if (DevExt->PowerDownLevel == PowerDeviceUnspecified ||
        DevExt->DevicePowerState != PowerDeviceD0) {

        OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
               ("SSSuspendDevice: PowerDownLevel not set or already "\
                "suspended, not suspending\n"));
        return;

    }

    //
    // Submit a device power IRP to our device
    //

    //
    // This constitutes a new I/O on the device, 
    //  so bump the oustanding I/O count
    //
    OsrIncrementOutstandingIoCount(DevExt,__FILE__,__LINE__);

    //
    // Setup the power down state to be the state 
    //  that we determined during the QUERY_CAPABILITIES
    //  processing
    //
    devicePowerState.DeviceState = (DEVICE_POWER_STATE)DevExt->PowerDownLevel;

    //
    // Initialize the power down event that our power completion
    //  routine will signal when the power down is complete
    //
    KeInitializeEvent(&powerDownCompleteEvent, NotificationEvent, FALSE);

    //
    // And ask the power manager to create and send a power down D-IRP 
    //  to our PDO. We always power the device down synchronously, so
    //  specify the synchronous power completion routine and pass
    //  an event to be set.
    //
    status = PoRequestPowerIrp(DevExt->PhysicalDeviceObject, 
                               IRP_MN_SET_POWER, 
                               devicePowerState, 
                               SSSynchronousPowerIrpCompletionFunc,
                               &powerDownCompleteEvent, 
                               NULL);

    //
    // We want to do this operation synchronously, so just wait
    //  for the operation to complete
    //
    if (status == STATUS_PENDING) {

        OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
                ("SSSuspendDevice: Waiting for the power irp to complete\n"));

        OsrWaitForSingleObject(&powerDownCompleteEvent);

    }


    //
    // The I/O is finished.
    //
    OsrDecrementOutstandingIoCount(DevExt,__FILE__,__LINE__);

    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
        ("SSSuspendDevice: PoRequestPowerIrp returned 0x%x (%s). Exiting...\n",
                status,OsrNtStatusToString(status)));

    //
    // Unlike the power UP case, we don't try to determine if the power
    //  down actually happened and update the SS state. This is because
    //  in the power up case there's no concept of, "hey, I didn't want that
    //  power up!" as there is in the power down case. So, it is the caller's
    //  responsiblity to determine that if at any point during the power down
    //  the power down request was cancelled and that the device actually
    //  needs to be powered up again. Basically, more decisions need to be
    //  made before we can get out of the SS_PROCESSING state so we just 
    //  return to the caller and let him deal with it.
    //

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
                                    ("SSSuspendDevice: Exited\n"));
    
}



#ifndef W2K

///////////////////////////////////////////////////////////////////////////////
//
// SSSuspendDeviceWithCallback
//
//      This routine requests an idle notification callback from the bus driver
//      and uses it to synchronously power down the device 
//
//  INPUTS:
//
//      DevExt  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID SSSuspendDeviceWithCallback(PUSBFX2LK_EXT DevExt) 
{
    
    PIRP idleCallbackIrp;
    PIO_STACK_LOCATION nextStack;
    NTSTATUS status;
    KIRQL oldIrql;
    PVOID waitObjects[2];

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
                        ("SSSuspendDeviceWithCallback: Entered\n"));
    
    //
    // We're built for XP and later, so we need to 
    //  submit an idle callback request and wait
    //  for the callback to be called by the bus
    //  driver before powering down the device
    //

    //
    // There's one REALLY annoying side effect of us 
    //  having to go through this path:
    //
    // ** There's no guarantee that the IRP won't complete
    // **  in error before, DURING, or after the idle 
    // **  callback running. Also, in the successful
    // **  case, the IRP's completion routine doesn't
    // **  run until the device is powered back up again
    //
    // So, the idle callback may or may not ever run and
    //  the IRP's completion routine may run now or 
    //  48 hours in the future. However, we still want
    //  to supply seemingly synchronous power down behaviour
    //  even when we require the use of the idle callback 
    //  (again, SS is hard enough so we're not going to 
    //  optimize).
    //
    // We'll use 2 events to do this. One that will be fired 
    //  within the callback (which, in the normal case, will 
    //  run within a relatively short time) and one event for
    //  the running of the IRP's completion routine. 
    //
    // If the event from the callback routine gets fired, 
    //  then the device is powered down and we're set. If the
    //  event from the completion routine gets fired, then the
    //  idle IRP was aborted by the bus driver for some reason.
    //

    //
    // Set the events to a known state
    //
    KeClearEvent(&DevExt->SSIdleCallbackCalled);
    KeClearEvent(&DevExt->SSIdleCompletionRoutineCalled);
    

    //
    // Fill in the idle callback structure that we need
    //  to pass along with the IRP
    //
    DevExt->SSIdleCallbackInfo.IdleCallback = SSUsbIdleCallback;
    DevExt->SSIdleCallbackInfo.IdleContext  = DevExt;

    //

⌨️ 快捷键说明

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