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

📄 usbfx2lk_selsusp.cpp

📁 基于vc++6.0环境的cypress USB 驱动源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
//    (C) Copyright 2005 OSR Open Systems Resources, Inc.
//    Copyright (c) 2000  Microsoft Corporation
//    All Rights Reserved
//
//    This sofware is supplied for instructional purposes only.
//
//    OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty
//    for this software.  THIS SOFTWARE IS PROVIDED  "AS IS" WITHOUT WARRANTY
//    OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
//    THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR
//    PURPOSE.  THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS
//    WITH YOU.  OSR's entire liability and your exclusive remedy shall not
//    exceed the price paid for this material.  In no event shall OSR or its
//    suppliers be liable for any damages whatsoever (including, without
//    limitation, damages for loss of business profit, business interruption,
//    loss of business information, or any other pecuniary loss) arising out
//    of the use or inability to use this software, even if OSR has been
//    advised of the possibility of such damages.  Because some states/
//    jurisdictions do not allow the exclusion or limitation of liability for
//    consequential or incidental damages, the above limitation may not apply
//    to you.
//
//    OSR Open Systems Resources, Inc.
//    105 Route 101A Suite 19
//    Amherst, NH 03031  (603) 595-6500 FAX: (603) 595-6503
//    email bugs to: bugs@osr.com
//
//
//    MODULE:
//
//      USBFx2LK_selsusp.cpp
//
//    ABSTRACT:
//
//      This file contains the routines that handle selective suspend
//      processing for the OSR USB FX2 Learning Kit Device
//
//    AUTHOR(S):
//
//      OSR Open Systems Resources, Inc.
// 
///////////////////////////////////////////////////////////////////////////////
#include "usbfx2lk.h"

#ifdef WPP_TRACING
//
// Include the necessary tmh file - this is 
//  just a matter of course if you're using WPP tracing.
//
extern "C" {
#include "usbfx2lk_selsusp.tmh"
}
#endif

//
// Forward declarations
//
#ifndef WIN2K
VOID SSUsbIdleCallback(PVOID Context);
NTSTATUS SSIdleNotificationCompletionRoutine(PDEVICE_OBJECT DeviceObject,
                                             PIRP Irp, PVOID Context);
#endif

VOID SSPowerUpCompleteUpdateSSState(PUSBFX2LK_EXT DevExt);
VOID SSSynchronousPowerIrpCompletionFunc(PDEVICE_OBJECT DeviceObject,
                                         UCHAR MinorFunction, 
                                         POWER_STATE PowerState,
                                         PVOID Context,
                                         PIO_STATUS_BLOCK IoStatus);
VOID SSAsynchronousPowerUpIrpCompletionFunc(PDEVICE_OBJECT DeviceObject,
                                            UCHAR MinorFunction, 
                                            POWER_STATE PowerState,
                                            PVOID Context,
                                            PIO_STATUS_BLOCK IoStatus);


///////////////////////////////////////////////////////////////////////////////
//
// EnableSelectiveSuspend
//
//      Enables selective suspend on the device
//
//  INPUTS:
//
//      DevExt  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      An appropriate NTSTATUS value
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID EnableSelectiveSuspend(PUSBFX2LK_EXT DevExt)
{
    KIRQL oldIrql;

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

    //
    // We're potentially going to change the state of the selective
    //  suspend members of our device extension, so we must acquire
    //  the selective suspend lock
    //
    KeAcquireSpinLock(&DevExt->SSLock,&oldIrql);

    //
    // ASSERT that we are not suspended or in the process of
    //  suspending. Our logic is written such that we assume that
    //  we are fully powered while enabling/disabling SS for the
    //  device. This is done by the calling function calling
    //  SSPowerDeviceIfSuspended before calling us
    //
    ASSERT(DevExt->SSState == SS_NOT_STARTED);
    ASSERT(KeReadStateEvent(&DevExt->SSDeviceNotSuspendedEvent));

    //
    // If the user doesn't ever want selective suspend, then
    //  we can just get out of here
    //
    if (!DevExt->SSEnabledByUser) {

        OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
            ("EnableSelectiveSuspend: SS disabled by user. Exiting\n"));

        KeReleaseSpinLock(&DevExt->SSLock,oldIrql);
        return;

    }


    //
    // See if we've already been here before. If so, we
    //  can just exit
    //
    if (DevExt->SSInitialized) {

        OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
            ("EnableSelectiveSuspend: SS already initialized. Exiting\n"));

        KeReleaseSpinLock(&DevExt->SSLock,oldIrql);
        return;

    }

    //
    // Default to not allowing the device to suspend right
    //  now. Because we're called in this routine only as the 
    //  result of an I/O request (either from the User or from
    //  the PnP manager) the I/O count is currently elevated.
    //  When it drops to 0, we will set this to TRUE
    //
    DevExt->SSDeviceCanNowSuspend = FALSE;

    //
    // We're ready to selectively suspend!
    //
    DevExt->SSInitialized = TRUE;

    KeReleaseSpinLock(&DevExt->SSLock,oldIrql);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
                                ("EnableSelectiveSuspend: Exit.\n"));

    return;
}

///////////////////////////////////////////////////////////////////////////////
//
// DisableSelectiveSuspend
//
//      Disables selective suspend on the device
//
//  INPUTS:
//
//      DevExt  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      An appropriate NTSTATUS value
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID DisableSelectiveSuspend(PUSBFX2LK_EXT DevExt)
{
    KIRQL oldIrql;

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

    //
    // We're potentially going to change the state of the selective
    //  suspend members of our device extension, so we must acquire
    //  the selective suspend lock
    //
    KeAcquireSpinLock(&DevExt->SSLock,&oldIrql);

    //
    // ASSERT that we are not suspended or in the process of
    //  suspending. Our logic is written such that we assume that
    //  we are fully powered while enabling/disabling SS for the
    //  device. This is done by the calling function calling
    //  SSPowerDeviceIfSuspended before calling us
    //
    ASSERT(DevExt->SSState == SS_NOT_STARTED);
    ASSERT(KeReadStateEvent(&DevExt->SSDeviceNotSuspendedEvent));

    //
    // Note that we're called here both when the user doesn't
    //  want SS anymore AND when SS just needs to be disabled 
    //  so that the device can stop or be removed. 
    //

    //
    // See if we've already been here before. If so, we
    //  can just exit
    //
    if (!DevExt->SSInitialized) {

        OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
            ("DisableSelectiveSuspend: SS not initialized. Exiting\n"));

        KeReleaseSpinLock(&DevExt->SSLock,oldIrql);
        return;

    }

    //
    // The device can't suspend right now...
    //
    DevExt->SSDeviceCanNowSuspend = FALSE;

    //
    // And it won't suspend in the future...
    //
    DevExt->SSInitialized = FALSE;

    KeReleaseSpinLock(&DevExt->SSLock,oldIrql);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
                                ("DisableSelectiveSuspend: Exit.\n"));

    return;
}

///////////////////////////////////////////////////////////////////////////////
//
// SSPowerDeviceIfSuspended
//
//      This routine synchronously powers the device up if it is 
//      suspended or in the process of being suspended
//
//  INPUTS:
//
//      DevExt  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      An appropriate NTSTATUS value
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
//      This routine synchronously powers the device and therefore
//      MUST be called at PASSIVE_LEVEL. 
//
///////////////////////////////////////////////////////////////////////////////
VOID SSPowerDeviceIfSuspended(PUSBFX2LK_EXT DevExt) 
{

    PAGED_CODE();
    
    //
    // See if the device is currently suspended. If it 
    //  is, this routine will attempt to asynchronously power 
    //  the device back up and will return TRUE. In that
    //  case, we want to synchronously wait for the power up 
    //  to occur.
    //
    // However, if this routine returns FALSE the device is 
    //  already powered up and we can simply return
    //
    if (SSPowerDeviceIfSuspendedAsync(DevExt)) {

        //
        // Wait for the suspend to be over
        //
        (VOID)OsrWaitForSingleObject(&DevExt->SSDeviceNotSuspendedEvent);
    }

    return;

}

///////////////////////////////////////////////////////////////////////////////
//
// SSPowerDeviceIfSuspendedAsync
//
//      This routine checks to see if the device is suspended or in the 
//      process of being suspsended and takes the appropriate action
//      to get the device powered again. 
//
//  INPUTS:
//
//      DevExt  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      TRUE if the device is suspended, FALSE if the device is 
//      fully powered
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN SSPowerDeviceIfSuspendedAsync(PUSBFX2LK_EXT DevExt) 
{
    BOOLEAN queuePowerUp = FALSE;
    BOOLEAN powerUpQueued = FALSE;
    KIRQL oldIrql;
#ifndef W2K
    PIRP idleIrp = NULL;
#endif

    PAGED_CODE();

    //
    // We'll need the SS lock for this 
    //
    KeAcquireSpinLock(&DevExt->SSLock,&oldIrql);

    //
    // Only if SS is setup to we need to do any 
    //  checks. 
    //
    if (DevExt->SSInitialized) {

        //
        // Indicate that we do not want the device to suspend
        //  because we're about to send a request to it.
        //
        DevExt->SSDeviceCanNowSuspend = FALSE;

        //
        // Check the state. 
        //
        switch (DevExt->SSState) {

            case SS_SUSPENDED: {

                DevExt->SSState = SS_PROCESSING;

                //
                // We'll be powering up...
                //
                queuePowerUp = TRUE;
                break;
            }

            case SS_PROCESSING: {

                powerUpQueued = TRUE;

#ifndef W2K

                //
                // On XP and later, we need to submit and idle
                //  notification IRP to the bus driver and wait
                //  to be called back in order to suspend. If we're
                //  on a hub with a device that is not suspending,
                //  this request may still be pending. If so, we
                //  need to cancel it before we can do anything
                //

                //
                // Grab the idle IRP out of the extension
                //
                idleIrp = DevExt->SSIdleIrp;

                //
                // And set it to NULL. This is the clue to the
                //  completion routine that we will be freeing
                //  the IRP
                //
                DevExt->SSIdleIrp = NULL;

#endif
                break;

            }
            case SS_NOT_STARTED: {

                //
                // Nothing to do here, we're powered up and active
                //  already
                //
                break;
            }
            default: {

                //
                // Shouldn't be here...
                //
                ASSERT(FALSE);
                break;

⌨️ 快捷键说明

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