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

📄 usbfx2lk_power.cpp

📁 基于vc++6.0环境的cypress USB 驱动源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    PUSBFX2LK_EXT       devExt = (PUSBFX2LK_EXT) Context; 
    PIO_STACK_LOCATION  ioStack = IoGetCurrentIrpStackLocation(Irp);
    POWER_STATE         powerState;

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("DevicePowerIoCompletionRoutine: Entered...\n"));

    switch (ioStack->MinorFunction) {

        case IRP_MN_SET_POWER: {

            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO, ("DevicePowerIoCompletionRoutine: IRP_MN_SET_POWER\n"));

            //
            // for SET_POWER we actually need to do some work...
            //
            
            // 
            // If the IRP failed for any reason, there is 
            // no reason to change any state.
            // 
            if(!NT_SUCCESS(Irp->IoStatus.Status)) {

                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_POWER_INFO, 
                    ("DevicePowerIoCompletionRoutine: Device Power Irp failed with status 0x%8.8x (%s)!\n",
                      Irp->IoStatus.Status, OsrNtStatusToString(Irp->IoStatus.Status)));

                break;
            
            }
  
            powerState.DeviceState = ioStack->Parameters.Power.State.DeviceState;
            
            //
            // Powering up the device or staying at the same
            //  power state...
            //
            if(devExt->DevicePowerState >= powerState.DeviceState) {
                
                OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO, 
                    ("DevicePowerIoCompletionRoutine: IRP_MN_SET_POWER Device powered up or stayed the same.\n"));
               
                //
                // Notify the power manager of the device power state change.
                //
                PoSetPowerState(DeviceObject,
                                DevicePowerState,
                                powerState);

                devExt->DevicePowerState = powerState.DeviceState;

                //
                // Restore our state to STATE_STARTED
                //
                OsrUpdateDeviceState(devExt, STATE_STARTED);

               
                //
                // If we powered up and Wait Wake is Enabled, then Issue a 
                //  Wait wake Request.
                //
                if(devExt->DevicePowerState == PowerDeviceD0 &&
                   devExt->WaitWakeEnable) {

                    IssueWaitWake(devExt);

                }

                //
                // If we have gone to full power, and we are in an applicable state
                // we need to restart the queues.
                // OsrProcessQueuedRequests checks the power state for us before 
                // starting any queues.
                //
                OsrProcessQueuedRequests(devExt);
        
            } else {
                OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO, 
                    ("DevicePowerIoCompletionRoutine: IRP_MN_SET_POWER Device powered down\n"));
            }



            //
            // Update the power state in our device extension
            //
            devExt->DevicePowerState = powerState.DeviceState;

            
            break;

        }
            
        default: {
            
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_POWER_INFO, ("DevicePowerIoCompletionRoutine: %08.8x %s\n",
                ioStack->MinorFunction,OsrMinorFunctionToString(ioStack->MajorFunction,ioStack->MinorFunction)));

            break;

        }
            
    }


    //
    // Let the power manager know we are ready to handle
    //  the next DevicePowerState power IRP. Why did we
    //  wait until the Irp came back up before calling this
    //  routine? Well, it's actually pretty subtle. 
    //  PoStartNextPowerIrp makes sure that we are only
    //  handling at most one D Irp and one S Irp at any 
    //  time. We're handling a D Irp here so if we called 
    //  PoStartNextPowerIrp on the way DOWN the stack, a 
    //  request to power up could be coming UP the stack 
    //  and a request to power down would be allowed to come 
    //  DOWN the stack (or vice versa). We'd break the implied 
    //  synchronization of only having one D Irp in the 
    //  stack at any time, which could cause race conditions...
    //
    //  Note that the failure case is different. If we need to
    //  fail an Irp in our OsrPower handler we can legally call 
    //  PoStartNextPowerIrp and then complete the Irp with an 
    //  error. 
    //
    //  Also note that if we receive a Power Irp with a minor
    //  function that we don't support we can also call 
    //  PoStartNextPowerIrp in OsrPower and just pass the Irp
    //  down without a completion routine.  
    //
    //  Is it confusing enough yet?
    //            
    PoStartNextPowerIrp(Irp);

    //
    // We're done with this request
    //
    OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("DevicePowerIoCompletionRoutine: Exiting!\n"));    

    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////
//
// DevicePowerRequestCompletionRoutine
//
//      Power request completion routine for device QUERY_POWER and SET_POWER IRPs.
//
//  INPUTS:
//
//      DeviceObject  - Pointer to device object.
//      MinorFunction - Power IRP's minor function code
//      PowerState    - The attempted device power state.
//      Context       - the device extension
//      IoStatus      - status block indicating the success or failure of the 
//                      power IRP.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      None.
//
//  IRQL:
//
//      This routine is called at IRQL <= DISPATCH_LEVEL
//
//  CONTEXT:
//
//      This routine is called in an arbitrary thread context
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID DevicePowerRequestCompletionRoutine(PDEVICE_OBJECT DeviceObject,UCHAR MinorFunction,
                            POWER_STATE PowerState,PVOID Context,PIO_STATUS_BLOCK IoStatus) 
{
    PUSBFX2LK_EXT   devExt = (PUSBFX2LK_EXT) Context;    
    PIRP            systemPowerIrp;

    UNREFERENCED_PARAMETER(DeviceObject);
    UNREFERENCED_PARAMETER(MinorFunction);
    UNREFERENCED_PARAMETER(PowerState);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("DevicePowerRequestCompletionRoutine: Entered...\n"));

    //
    // Get the system power IRP from our context
    //
    systemPowerIrp = devExt->SystemPowerIrp;


    //
    // This should not happen
    //
    ASSERT(NULL != systemPowerIrp);

    //
    // NULL out our temp storage for the IRP
    //
    devExt->SystemPowerIrp = NULL;


    //
    // Let the power manager know we are ready to handle
    // the next SystemPowerState power IRP.
    //            
    PoStartNextPowerIrp(systemPowerIrp);
    
    // 
    // We complete the system power IRP here with the returned device
    // power IRP's status.  If any driver failed the device power IRP, 
    // the error is propagated to the system IRP this way.
    //
    systemPowerIrp->IoStatus.Status = IoStatus->Status;

    //
    // And we're done!
    //
    IoCompleteRequest(systemPowerIrp, IO_NO_INCREMENT);


    //
    // We're done with this request. We acquired the
    //  lock in OsrPower, so we'll use OsrPower as the 
    //  tag here also
    //
    OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_POWER_INFO, ("DevicePowerRequestCompletionRoutine: Exiting!\n"));

}


///////////////////////////////////////////////////////////////////////////////
//
// IssueWaitWake
//
//      This routine issues a WAIT_WAKE request in order enable the USB device
//      to awaken in response to a user hitting the wake up button on the device.
//
//  INPUTS:
//
//      DevExt  - Pointer to our Device Extension.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      None.
//
//  IRQL:
//
//      This routine is called at IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      This routine is called in an arbitrary thread context
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS IssueWaitWake(PUSBFX2LK_EXT DevExt)
{
    NTSTATUS    status;
    POWER_STATE wakeState;

    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
    VALID_DEVEXT(DevExt);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_WAIT_WAKE, ("IssueWaitWake: Entered\n"));

    //
    // Make sure that there is not a currently outstanding WaitWake request.
    //
    if(InterlockedExchange(&DevExt->FlagWWOutstanding, 1)) {
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_WAIT_WAKE, 
                    ("IssueWaitWake: Wait Wake already outstanding, exit processing.\n"));
        return STATUS_DEVICE_BUSY;
    }

    InterlockedExchange(&DevExt->FlagWWCancel, 0);

    //
    // Set up the System State from which the USB device is capable of waking 
    // up the system.  Note that this information comes from the Device Capabilites
    // information.   This information must be filled in before we do the IssueWaitWake
    // call.
    //
    wakeState.SystemState = DevExt->DeviceCapabilities.SystemWake;

    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_WAIT_WAKE, 
                ("IssueWaitWake: Issue Wait Wake for System state transition to %s\n", 
                OsrPrintSystemPowerState(wakeState.SystemState)));

    //
    // Request a Power Irp to deliver the Wait Wake Request.
    status = PoRequestPowerIrp(DevExt->PhysicalDeviceObject, 
                                 IRP_MN_WAIT_WAKE,
                                 wakeState, 
                                 (PREQUEST_POWER_COMPLETE) WaitWakeCallback,
                                 DevExt, 
                                 &DevExt->WaitWakeIrp);

    if(!NT_SUCCESS(status)) {
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_WAIT_WAKE, 
            ("IssueWaitWake: Device Power Irp failed with status 0x%8.8x (%s)!\n",
                status, OsrNtStatusToString(status)));

        InterlockedExchange(&DevExt->FlagWWOutstanding, 0);
    }

    //
    // Retun the Status to the Caller.
    //

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_WAIT_WAKE, ("IssueWaitWake: Exit\n"));

    return status;
}

///////////////////////////////////////////////////////////////////////////////
//
// CancelWaitWake
//
//      This routine cancels an outstanding WAIT_WAKE request.
//
//  INPUTS:
//
//      DevExt  - Pointer to our Device Extension.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      None.
//
//  IRQL:
//
//      This routine is called at IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      This routine is called in an arbitrary thread context
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID CancelWaitWake(PUSBFX2LK_EXT DevExt)
{
    PIRP Irp;

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_WAIT_WAKE,("CancelWaitWake: Entered.\n"));

    //
    // Attempt to grab the WaitWake irp out of the Device Extension.
    //
    Irp = (PIRP) InterlockedExchangePointer((volatile PVOID*) &DevExt->WaitWakeIrp, NULL);

    //
    // See if we got the Irp, if we did, then we can try to cancel it.
    //
    if(Irp) {

        OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_WAIT_WAKE, 
                ("CancelWaitWake: Canceling Wait Wake Irp.\n"));

        //
        // Got the Irp, Cancel It.
        //
        IoCancelIrp(Irp);

        //
        //  Indicate that the Irp was canceled so that the
        // WaitWakeCompletion routine knows what is going on.
        //
        if(InterlockedExchange(&DevExt->FlagWWCancel, 1)) {

            //
            // Tell the Power Manager that we are ready to
            // handle another Power Irp.
            //
            PoStartNextPowerIrp(Irp);

            //
            // Complete the Wait Wake Irp with a Canceled
            // status.
            //
            Irp->IoStatus.Status = STATUS_CANCELLED;
            Irp->IoStatus.Information = 0;

            IoCompleteRequest(Irp, IO_NO_INCREMENT);
        }    
    }
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_WAIT_WAKE,("CancelWaitWake: Exit.\n"));
}

///////////////////////////////////////////////////////////////////////////////
//
// WaitWakeCompletionRoutine
//

⌨️ 快捷键说明

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