Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Help regarding power management and USB selective suspend with UMDF2

Paul_BPaul_B Member Posts: 6

Hello,

I am new to windows driver development and need help regarding power management and selective suspend.

I am writing an UMD2 driver for a custom USB device. My starting point for the driver code was https://github.com/microsoft/Windows-driver-samples/tree/master/usb/umdf2_fx2

My driver exposes a dozen of IOCTL that are processed sequentially through one power managed I/O queue. Most of the IOCLs are translated to one or several synchronous USB control requests. Few IOCTLs however will start some asynchronous operation on the device. In this case, a background thread is started to issue one USB read on the input pipe with an infinite timeout. At any time, the device will send a USB wakeup event and push the data on the IN endpoint. The USB read request will complete and the IOCTL will return the device data.

This works pretty well but I am now trying to enable selective suspend on the driver to limit overall power consumption while waiting for asynchronous operation to complete or when device is doing nothing.

I have made my driver the policy owner and have defined the idle and wake-up power policy as follow:

WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend);
idleSettings.DxState = PowerDeviceD2;
idleSettings.Enabled = WdfTrue;
idleSettings.UserControlOfIdleSettings = IdleAllowUserControl;
idleSettings.IdleTimeout = 10000;
idleSettings.ExcludeD3Cold = WdfTrue; 

WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);
wakeSettings.Enabled = WdfTrue;
wakeSettings.DxState = PowerDeviceD2;

However, I have noticed, while the driver is idling (no IOCTL to process), the framework will call EvtDeviceD0Exit(TargetState=WdfPowerDeviceD2) after idle timeout, but will immediately call EvtDeviceD0Entry(PreviousState=WdfPowerDeviceD2) and will do that every idle timeout seconds (there was only my device on the USB hub).

I am a bit surprised by this behavior and was expecting EvtDeviceD0Entry() to be called only when there is an IOCTL or when the device or bus send a USB wakeup event. **Is it expected ? **

My other question is how to put the USB bus in suspended state while my INPUT request is pending ?

I was thinking about canceling the USB read request after some timeout to let the USB bus be suspended. When the device sends the wakeup signal, the driver would re-issue the USB read to get the data and complete the pending IOCTL. Is it the right approach ?

And my final question is how to catch events in the driver when the system is about to go into suspend or hibernate or when the usb bus power is about to get shutdown ?

I was surprised to see that EvtDeviceD0Exit(TargetState=WdfPowerDeviceD3) is only called when disabling the device from the device manager. It is not called when the system goes into sleep. And I was also surprised to see the system force killing my driver after some time because of too much power drain, which cause the device to stop working upon system wakeup.

Thanks for your help!

Comments

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,090

    I am a bit surprised by this behavior and was expecting EvtDeviceD0Entry() to be called

    I'm surprised by that behavior as well. Your expectations are the same as mine.

    Your device isn't waking itself after going into idle, is it? That's the most common cause for what you're seeing.

    When the system transitions to hibernate a low power state (S4), and your device is in D0, you don't get called at D0Exit?

    BTW... "idleSettings.Enabled = WdfTrue;" should be "idleSettings.Enabled = WdfUseDefault; " Because you set "idleSettings.UserControlOfIdleSettings = IdleAllowUserControl" -- This isn't your problem, but it's likely not what you want as written.

    These settings all interact, especially for USB, in complex ways. MY personal approach is to specify as few of these parameters as possible. For example, I wouldn't specifically assign DxState unless you feel like you really need to. Let the Framework work with the rest of the system to figure it out (it's going to be USB Selective Suspend in any case).

    Hope that's at least SOME help,

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Paul_BPaul_B Member Posts: 6

    Thanks for your answer.

    When settings "idleSettings.IdleCaps = IdleCannotWakeFromS0" I have the "expected" behavior (I don't renter in D0 immediately), but I don't know if with this configuration, the underlying USB bus goes into selective suspend.

    I guess I will have to look closer to the device to see if it is behaving properly and try to spy what happens on the USB bus.

    For transition to S4 you are right, I have a notification. But I don't have any when going into suspend. That could be alright except, because of modern standby I suppose, the system ends-up killing my driver...

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,090

    I’m sure somebody at MSFT has a clear, detailed, vision of how Modern Standby is supposed to work these days with each and every class of device... but I (I’m embarrassed to say) sure don’t.

    You need a USB bus analyzer (a real one, not a software one) to verify what’s going on.

    Can you say more about what “killing your driver” means? Have you dumped your WDF log (!wdfkd.wdflogdump)? That could be enlightening. Also, be sure both WDF verifier, verbose tracing, and Windows Driver Verifier are enables when you test... just in case you can get some hints.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Paul_BPaul_B Member Posts: 6

    The service using my driver returns 0x8007050B (ERROR_DRIVER_PROCESS_TERMINATED) when I wake up the PC.

    And the system events logs shows the following messages:

    • USB device draining system power when system is idle.
      USB Device: VID: xxxx PID: yyyy REV: wwww
      Removal action failed: SkippedAsRecentIoObservered

    • The device 'xxxxxx' (location Port#0001.Hub_#0004) is offline due to a user-mode driver crash. Windows will attempt to restart the device 5 more times. Please contact the device manufacturer for more information about this problem._

    • A problem has occurred with one or more user-mode drivers and the hosting process has been terminated. This may temporarily interrupt your ability to access the devices.

    The last trace from my driver is when I enter WdfUsbTargetPipeReadSynchronously() to wait for the device data.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 13,627

    One of the awkwardnesses is that the USB power model does not align perfectly with the Windows power model. USB Selective Suspend means the system is allows to kill power to the entire hub containing your device. If your device has any state information that doesn't survive a power cut, then you have to be able to bring it back to life. That takes some thought.

    You've read this? It's about UMDF 1, but some of the concepts are still useful.

    https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/selective-suspend-in-umdf-drivers

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Pavel_APavel_A Member Posts: 2,739
    edited July 10

    @OP has this custom USB device been validated, passed USB compliance tests? If not, there's no reason to have any expectations and be surprised.
    ("works in Linux" does not count as validation).
    -- pa

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,090

    Let me once again recommend you looking at the output from !wdflogdump, with verbose tracing enabled. This can provide additional info for ALL the issues you are seeing.

    The last trace from my driver is when I enter WdfUsbTargetPipeReadSynchronously() to wait for the device data

    Hmmmm... Is this a long-running read, the WdfUsbTargetPipeReadSynchronously. The "usual" way we "wait for device data" (when you always want to get the data that may be arriving on a given IN endpoint) is with a Continuous Reader.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Paul_BPaul_B Member Posts: 6

    @Tim_Roberts

    One of the awkwardnesses is that the USB power model does not align perfectly with the Windows power model. USB Selective Suspend means the system is allows to kill power to the entire hub containing your device. If your device has any state information that doesn't survive a power cut, then you have to be able to bring it back to life. That takes some thought.

    Maybe I missed something but I thought you could limit selective suspend to only stop polling devices to limit power consumption. If device is bus-powered and has wake-up capability, it would imply you cannot completely cut the device power. This was my assumption anyway, but my short experience with windows and usb is that the behavior often depends on the platform and rarely matches my understanding...

    Indeed, my device has state information that are shared with a service on the PC. We have no control on the service and the service expects the device to be always running. But if I have a notification about when the power will be cut and if the device can re-enumerate cleanly afterwards, I could live with that for now.

    You've read this? It's about UMDF 1, but some of the concepts are still useful.

    I did and tried to match the settings with UMDF 2, but I must have missed something.

    @Peter_Viscarola_(OSR)

    I have tried to run !wdflogdump per your recommendation but I have a hard time to interpret all the power state changes.
    What I would like to know is the cause for going back to D0 immediately but I am not sure it appears in the dump attach.
    We have ordered a logic analyzer to better understand what happens at the device level.

    I will look into the continuous reader as it is cleaner than using an infinite timeout.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,090

    Hmmmm... The only thing that I see from that trace is that your device is (a) entering Selective Suspend, (b) waking itself up.

    Is it possible your device is generating an interrupt while you have it "asleep"?? Because that LOOKS to me like it could be what's happening... your device is generating an interrupt and that's being interpreted as a wake request. I need to emphasize that is a guess.

    And yes... If what you want is to "always have a Request in progress in case the device generates something" the Continuous Reader is definitely the way to go.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Writing WDF Drivers 7 Dec 2020 LIVE ONLINE
Internals & Software Drivers 25 Jan 2021 LIVE ONLINE
Developing Minifilters 8 March 2021 LIVE ONLINE