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

📄 usbfx2lk_selsusp.cpp

📁 基于vc++6.0环境的cypress USB 驱动源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    // This constitutes a new I/O on the device, 
    //  so bump the oustanding I/O count
    //
    OsrIncrementOutstandingIoCount(DevExt,__FILE__,__LINE__);


    //
    // And allocate an IRP of the appropriate size
    //
    idleCallbackIrp = IoAllocateIrp(DevExt->DeviceToSendIrpsTo->StackSize,
                                    FALSE);

    if (!idleCallbackIrp) {

        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_SELECTIVE_SUSPEND,
         ("SSSuspendDeviceWithCallback: IoAllocateIrp returned NULL. Exiting...\n"));
        return;

    }

    //
    // Get the next stack location for the IRP and 
    //  set it up to be an idle notification request
    //
    nextStack = IoGetNextIrpStackLocation(idleCallbackIrp);

    nextStack->MajorFunction = 
                    IRP_MJ_INTERNAL_DEVICE_CONTROL;

    nextStack->Parameters.DeviceIoControl.IoControlCode = 
                    IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION;

    nextStack->Parameters.DeviceIoControl.Type3InputBuffer =
                    &DevExt->SSIdleCallbackInfo;

    nextStack->Parameters.DeviceIoControl.InputBufferLength =
                    sizeof(USB_IDLE_CALLBACK_INFO);

    //
    // Setup our completion routine that will free the memory
    //  for this IRP
    //
    IoSetCompletionRoutine(idleCallbackIrp, 
                           SSIdleNotificationCompletionRoutine,
                           DevExt, 
                           TRUE, 
                           TRUE, 
                           TRUE);

    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
            ("SSSuspendDeviceWithCallback: Submitting idle IRP 0x%p.\n", 
                idleCallbackIrp));

    //
    // Set this IRP up in our device extension. We need to
    //  keep track of this IRP because it will pend
    //  forever if we are on a hub with a device that 
    //  isn't suspending.
    //
    KeAcquireSpinLock(&DevExt->SSLock,&oldIrql);
    
    //
    // Shouldn't already have a request pending
    //
    ASSERT(DevExt->SSIdleIrp == NULL);

    //
    // There's another race condition that we have to contend
    //  with in this case. SSPowerDeviceIfSuspended may have 
    //  already executed and looked to see if there is 
    //  an Idle IRP pending. Because we haven't set the
    //  field yet, it will think that the device is just
    //  in the middle of powering up and will simply 
    //  wait for the power up event. That means that we 
    //  could sit here waiting for the idle notification
    //  callback to occur (which may not EVER happen) while
    //  the rest of our code is waiting for a device power
    //  up to happen, leading to a livelock in the driver. 
    //
    // We'll cover this race condition by adding an extra
    //  check here to make sure that the device hasn't 
    //  become busy while we were building the idle IRP. 
    //  If it has, we'll just get out of here...
    //
    if (DevExt->SSDeviceCanNowSuspend == FALSE) {

        OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
            ("SSSuspendDeviceWithCallback: Device became busy while building "\
                    "IDLE IRP. Exiting.\n"));

        //
        // Free the IRP we built 
        //
        IoFreeIrp(idleCallbackIrp);

        KeReleaseSpinLock(&DevExt->SSLock,oldIrql);

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

        return;

    }

    // 
    // Setup a pointer to the idle IRP in the 
    //  device extension
    //
    DevExt->SSIdleIrp = idleCallbackIrp;

    KeReleaseSpinLock(&DevExt->SSLock,oldIrql);

    //
    // And submit the IRP down to the lower driver. 
    //
    status = IoCallDriver(DevExt->DeviceToSendIrpsTo,
                          idleCallbackIrp);

    if (NT_SUCCESS(status)) {

        //
        // If we got a successful status, wait for the 
        //  idle callback to fire and the device to 
        //  power down OR for the IRP's completion routine 
        //  to be called because there was some sort of error
        //  that occurred before the device could idle
        //
        OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
            ("SSSuspendDeviceWithCallback: Waiting for suspend idle callback "\
                            "or completion routine to fire...\n"));

        waitObjects[0] = &DevExt->SSIdleCallbackCalled;
        waitObjects[1] = &DevExt->SSIdleCompletionRoutineCalled;

        //
        // Wait on our above two events. 
        //
        status = OsrWaitForMultipleObjects(2,
                                           waitObjects,
                                           WaitAny,
                                           NULL);

        if (status == STATUS_WAIT_0) {

            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
                ("SSSuspendDeviceWithCallback: Idle callback fired!\n"));

        } else  if (status == STATUS_WAIT_1) {

            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
                ("SSSuspendDeviceWithCallback: Completion routine fired!\n"));

        } else {

            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
                ("SSSuspendDeviceWithCallback: KeWaitForMultipleObjects "\
                                    "returned unknown status 0x%x (%s).\n",
                status,OsrNtStatusToString(status)));

        }


    } else {

        //
        // The IRP was failed before the idle callback was 
        //  queued. Not much we can do, the completion routine
        //  will free the IRP
        //
        OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND,
            ("SSSuspendDeviceWithCallback: Idle request failed, bus returned "\
                                                     "0x%x (%s). Exiting...\n",
                    status,OsrNtStatusToString(status)));


    }

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

}



///////////////////////////////////////////////////////////////////////////////
//
// SSUsbIdleCallback
//
//      This routine is the USB idle callback that does the actually
//      suspending of the device when built for XP and later
//
//  INPUTS:
//
//      Context  -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID SSUsbIdleCallback(PVOID Context)
{
    PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT)Context;
        
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
            ("SSUsbIdleCallback: Entered\n"));


    //
    // And now power the device down
    // 
    SSSuspendDevice(devExt);

    KeSetEvent(&devExt->SSIdleCallbackCalled, 
               EVENT_INCREMENT,
               FALSE);

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


}

///////////////////////////////////////////////////////////////////////////////
//
// SSIdleNotificationCompletionRoutine
//
//      This routine is the completion routine for the IRP used to submit the
//      USB idle callback
//
//  INPUTS:
//
//      DeviceObject - We allocated the IRP, so this is NULL
//
//      Irp          - The idle notification IRP
//
//      Context      -  One of our device extensions
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      STATUS_MORE_PROCESSING_REQUIRED
//
//  IRQL:
//
//      IRQL <= DISPATCH_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS SSIdleNotificationCompletionRoutine(PDEVICE_OBJECT DeviceObject,
                                             PIRP Irp, PVOID Context)
{
    PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT)Context;
    KIRQL oldIrql;
    PIRP idleIrp;

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

    KeAcquireSpinLock(&devExt->SSLock,&oldIrql);
    
    //
    // Let's see if someone else didn't get to this
    //  first
    //
    idleIrp = devExt->SSIdleIrp;

    devExt->SSIdleIrp = NULL;

    KeReleaseSpinLock(&devExt->SSLock,oldIrql);

    if (idleIrp) {

        //
        // If we got the IRP, we free it. Otherwise let the
        //  person who cancelled the IRP free it. 
        //
        IoFreeIrp(idleIrp);

    }

    KeSetEvent(&devExt->SSIdleCompletionRoutineCalled, 
               EVENT_INCREMENT,
               FALSE);


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

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

    return STATUS_MORE_PROCESSING_REQUIRED;

}


#endif





///////////////////////////////////////////////////////////////////////////////
//
// SSSynchronousPowerIrpCompletionFunc
//
//      Generic SYNCHRONOUS selective suspend D-IRP power completion routine
//
//  INPUTS:
//
//      DeviceObject  - Not used
//      
//      MinorFunction - Not used
//
//      PowerState    - Not used
//
//      Context       - An event to signal the completion of the D-IRP
//
//      IoStatus      - Not used
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL <= DISPATCH_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID SSSynchronousPowerIrpCompletionFunc(PDEVICE_OBJECT DeviceObject,
                                         UCHAR MinorFunction, 
                                         POWER_STATE PowerState,
                                         PVOID Context,
                                         PIO_STATUS_BLOCK IoStatus)
{

    PKEVENT completeEvent = (PKEVENT)Context;

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

    KeSetEvent(completeEvent, EVENT_INCREMENT, FALSE);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
            ("SSSynchronousPowerIrpCompletionFunc: Exiting\n"));

}

///////////////////////////////////////////////////////////////////////////////
//
// SSAsynchronousPowerUpIrpCompletionFunc
//
//      ASYNCHRONOUS selective suspend for power up D-IRP completion 
//      routine
//
//  INPUTS:
//
//      DeviceObject  - Not used
//      
//      MinorFunction - Not used
//
//      PowerState    - Not used
//
//      Context       - One of our device extensions
//
//      IoStatus      - Not used
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL <= DISPATCH_LEVEL
//
//  CONTEXT:
//
//      Arbitrary
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID SSAsynchronousPowerUpIrpCompletionFunc(PDEVICE_OBJECT DeviceObject,
                                            UCHAR MinorFunction, 
                                            POWER_STATE PowerState,
                                            PVOID Context,
                                            PIO_STATUS_BLOCK IoStatus)
{

    PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT)Context;

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

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

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

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_SELECTIVE_SUSPEND,
            ("SSAsynchronousPowerUpIrpCompletionFunc: Exiting\n"));

}


⌨️ 快捷键说明

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